diff --git a/src/Draft/Draft_Modification_1.cxx b/src/Draft/Draft_Modification_1.cxx index 47c00b581e..e7928c9766 100644 --- a/src/Draft/Draft_Modification_1.cxx +++ b/src/Draft/Draft_Modification_1.cxx @@ -1549,6 +1549,58 @@ void Draft_Modification::Perform () Vf.Reverse(); Vl.Reverse(); } + + if(myVMap.Contains(Vf) && myVMap.Contains(Vl)) + { + //Here, we compare directions of the source edge (from input shape) + //and corresponding selected part of the intersection edge. + //If these directions are opposite then we reverse intersection edge + //and recompute corresponding vertex-parameters. + + Standard_Real aParF = myVMap.ChangeFromKey(Vf).Parameter(edg); + Standard_Real aParL = myVMap.ChangeFromKey(Vl).Parameter(edg); + + if(aParL < aParF) + { + Draft_EdgeInfo& aEinf = myEMap.ChangeFromKey(edg); + TopLoc_Location aLoc; + Standard_Real aF = 0.0, aL = 0.0; + const Handle(Geom_Curve) aSCurve = BRep_Tool::Curve(edg, aF, aL); + Handle(Geom_Curve) anIntCurv = aEinf.Geometry(); + gp_Pnt aPf, aPl; + gp_Vec aDirNF, aDirNL, aDirOF, aDirOL; + aSCurve->D1(BRep_Tool::Parameter(Vf, edg), aPf, aDirOF); + aSCurve->D1(BRep_Tool::Parameter(Vl, edg), aPl, aDirOL); + anIntCurv->D1(aParF, aPf, aDirNF); + anIntCurv->D1(aParL, aPl, aDirNL); + + aDirNF.Normalize(); + aDirNL.Normalize(); + aDirOF.Normalize(); + aDirOL.Normalize(); + + const Standard_Real aCosF = aDirNF.Dot(aDirOF), aCosL = aDirNL.Dot(aDirOL); + const Standard_Real aCosMax = Abs(aCosF) > Abs(aCosL) ? aCosF : aCosL; + + if(aCosMax < 0.0) + { + Standard_Integer anErr = 0; + anIntCurv->Reverse(); + aEinf.ChangeGeometry() = anIntCurv; + Standard_Real aPar = Parameter(aEinf.Geometry(), aPf, anErr); + if(anErr == 0) + { + myVMap.ChangeFromKey(Vf).ChangeParameter(edg) = aPar; + } + aPar = Parameter(aEinf.Geometry(), aPl, anErr); + if(anErr == 0) + { + myVMap.ChangeFromKey(Vl).ChangeParameter(edg) = aPar; + } + } + } + } + Standard_Real pf,pl,tolerance; if (!NewParameter(Vf,edg,pf,tolerance)) { pf = BRep_Tool::Parameter(Vf,edg); diff --git a/src/ElCLib/ElCLib.hxx b/src/ElCLib/ElCLib.hxx index 6373a6307a..6c56554d39 100644 --- a/src/ElCLib/ElCLib.hxx +++ b/src/ElCLib/ElCLib.hxx @@ -78,6 +78,8 @@ public: //! Return a value in the range by //! adding or removing the period to //! . + //! ATTENTION!!! + //! It is expected but not checked that (ULast > UFirst) Standard_EXPORT static Standard_Real InPeriod (const Standard_Real U, const Standard_Real UFirst, const Standard_Real ULast); //! Adjust U1 and U2 in the parametric range UFirst diff --git a/src/GeomInt/GeomInt_IntSS.cxx b/src/GeomInt/GeomInt_IntSS.cxx index b44c0c1d58..0e2d7c9bcc 100644 --- a/src/GeomInt/GeomInt_IntSS.cxx +++ b/src/GeomInt/GeomInt_IntSS.cxx @@ -14,20 +14,10 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include //======================================================================= //function : Perform diff --git a/src/GeomInt/GeomInt_IntSS_1.cxx b/src/GeomInt/GeomInt_IntSS_1.cxx index f95970b1c9..8ba1c0c3ae 100644 --- a/src/GeomInt/GeomInt_IntSS_1.cxx +++ b/src/GeomInt/GeomInt_IntSS_1.cxx @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -42,14 +41,12 @@ #include #include #include -#include -#include #include #include #include #include #include -#include +#include //======================================================================= //function : AdjustUPeriodic @@ -552,134 +549,9 @@ void GeomInt_IntSS::MakeCurve(const Standard_Integer Index, //######################################## // Analytic //######################################## - case IntPatch_Analytic: { - IntSurf_Quadric quad1,quad2; - // - GetQuadric(myHS1, quad1); - GetQuadric(myHS2, quad2); - //========= - IntPatch_ALineToWLine convert (quad1, quad2); + case IntPatch_Analytic: + //This case was processed earlier (in IntPatch_Intersection) - if (!myApprox) { - Handle(Geom2d_BSplineCurve) aH1, aH2; - // - aNbParts=myLConstruct.NbParts(); - for (i=1; i<=aNbParts; i++) { - myLConstruct.Part(i, fprm, lprm); - Handle(IntPatch_WLine) WL = - convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm); - // - if(myApprox1) { - aH1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True); - } - - if(myApprox2) { - aH2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False); - } - sline.Append(MakeBSpline(WL,1,WL->NbPnts())); - slineS1.Append(aH1); - slineS2.Append(aH2); - } - } // if (!myApprox) - - else { // myApprox=TRUE - GeomInt_WLApprox theapp3d; - Standard_Real tol2d = myTolApprox; - // - theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True); - - aNbParts=myLConstruct.NbParts(); - for (i=1; i<=aNbParts; i++) { - myLConstruct.Part(i, fprm, lprm); - Handle(IntPatch_WLine) WL = - convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm); - - theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts()); - if (!theapp3d.IsDone()) { - // - Handle(Geom2d_BSplineCurve) aH1, aH2; - - if(myApprox1) { - aH1 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True); - } - - if(myApprox2) { - aH2 = MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False); - } - sline.Append(MakeBSpline(WL,1,WL->NbPnts())); - slineS1.Append(aH1); - slineS2.Append(aH1); - } - // - else { - if(myApprox1 || myApprox2) { - if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { - myTolReached2d = theapp3d.TolReached2d(); - } - } - - if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { - myTolReached3d = theapp3d.TolReached3d(); - } - - Standard_Integer aNbMultiCurves, nbpoles; - aNbMultiCurves=theapp3d.NbMultiCurves(); - for (j=1; j<=aNbMultiCurves; j++) { - const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j); - - nbpoles = mbspc.NbPoles(); - TColgp_Array1OfPnt tpoles(1, nbpoles); - mbspc.Curve(1, tpoles); - Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_CheckBSplineCurve Check(BS, myTolCheck, myTolAngCheck); - Check.FixTangent(Standard_True,Standard_True); - // - sline.Append(BS); - // - if(myApprox1) { - TColgp_Array1OfPnt2d tpoles2d(1,nbpoles); - mbspc.Curve(2,tpoles2d); - Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck); - newCheck.FixTangent(Standard_True,Standard_True); - slineS1.Append(BS2); - } - else { - slineS1.Append(H1); - } - - if(myApprox2) { - TColgp_Array1OfPnt2d tpoles2d(1, nbpoles); - Standard_Integer TwoOrThree; - TwoOrThree=myApprox1 ? 3 : 2; - mbspc.Curve(TwoOrThree, tpoles2d); - Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck); - newCheck.FixTangent(Standard_True,Standard_True); - // - slineS2.Append(BS2); - } - else { - slineS2.Append(H1); - } - // - }// for (j=1; j<=aNbMultiCurves; j++) { - }// else from if (!theapp3d.IsDone()) - }// for (i=1; i<=aNbParts; i++) { - }// else { // myApprox=TRUE - }// case IntPatch_Analytic: break; //######################################## diff --git a/src/IntAna/IntAna_Curve.cxx b/src/IntAna/IntAna_Curve.cxx index 12e3baaf46..f644f73f84 100644 --- a/src/IntAna/IntAna_Curve.cxx +++ b/src/IntAna/IntAna_Curve.cxx @@ -267,12 +267,13 @@ Standard_Real& sint, Standard_Real& SigneSqrtDis) const { + const Standard_Real aRelTolp = 1.0+Epsilon(1.0), aRelTolm = 1.0-Epsilon(1.0); Standard_Real Theta=theta; Standard_Boolean SecondSolution=Standard_False; - if((ThetaDomainSup) && (!TwoCurves)) || - (Theta>(DomainSup+DomainSup-DomainInf+0.00000000000001))) { + if((ThetaDomainSup*aRelTolp) && (!TwoCurves)) || + (Theta>(DomainSup+DomainSup-DomainInf)*aRelTolp)) { SigneSqrtDis = 0.; Standard_DomainError::Raise("IntAna_Curve::Domain"); } @@ -302,11 +303,11 @@ +Z0CosSin*costsint; - Standard_Real Discriminant = B*B-4.0*A*C; + const Standard_Real aDiscriminant = Max(B*B-4.0*A*C, 0.0); - if(Abs(A)<=0.000000001) { + if(Abs(A)<=Precision::PConfusion()) { //-- cout<<" IntAna_Curve:: Internal UV Value : A="< Abs(A)="< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include + +#include +#include +#include +#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -static - gp_Pnt DefineDU(const Handle(IntPatch_ALine)& aline, - const Standard_Real U, - Standard_Real& DU, - const Standard_Real CurvDef, - const Standard_Real AngDef); +//======================================================================= +//function : AddPointIntoLine +//purpose : +//======================================================================= +static inline void AddPointIntoLine(Handle(IntSurf_LineOn2S) theLine, + const Standard_Real* const theArrPeriods, + IntSurf_PntOn2S &thePoint, + IntPatch_Point* theVertex = 0) +{ + if(theLine->NbPoints() > 0) + { + if(thePoint.IsSame(theLine->Value(theLine->NbPoints()), Precision::Confusion())) + return; -static - Standard_Boolean SameCurve(const Handle(Adaptor2d_HCurve2d)& C1, - const Handle(Adaptor2d_HCurve2d)& C2); + IntPatch_SpecialPoints::AdjustPointAndVertex(theLine->Value(theLine->NbPoints()), + theArrPeriods, thePoint, theVertex); + } -static - void RecadreMemePeriode(Standard_Real& u1, - Standard_Real& u2, - const Standard_Real anu1, - const Standard_Real anu2); + theLine->Add(thePoint); +} -static - void CorrectFirstPartOfLine(Handle(IntSurf_LineOn2S)& LinOn2S, - const Standard_Real ref_u1, - const Standard_Real ref_u2, - Standard_Real& new_u1, - Standard_Real& new_u2); +//======================================================================= +//function : AddVertexPoint +//purpose : Extracts IntSurf_PntOn2S from theVertex and adds result in theLine. +//======================================================================= +static void AddVertexPoint(Handle(IntSurf_LineOn2S)& theLine, + IntPatch_Point &theVertex, + const Standard_Real* const theArrPeriods) +{ + IntSurf_PntOn2S anApexPoint = theVertex.PntOn2S(); + AddPointIntoLine(theLine, theArrPeriods, anApexPoint, &theVertex); +} -// -static - void RefineParameters(const Handle(IntPatch_ALine)& aALine, - const Standard_Real aTb, - const Standard_Real aTe, - const Standard_Real aTx, - const Standard_Integer iDir, - const IntSurf_Quadric& aQuadric, - const Standard_Real aTol3D, - Standard_Real& aUx, - Standard_Real& aVx); -static - Standard_Boolean FindNearParameter(const Handle(IntPatch_ALine)& aALine, - const Standard_Real aTx, - const Standard_Integer iDir, - const Standard_Real aTol3D, - Standard_Real& aT1); -static - Standard_Boolean IsApex(const IntSurf_Quadric& aQuadric, - const Standard_Real aVx, - const Standard_Real aTol3D); -// +//======================================================================= +//function : IsPoleOrSeam +//purpose : Processes theVertex depending on its type +// (pole/apex/point on boundary etc.) and adds it in theLine. +// theSingularSurfaceID contains the ID of surface with +// special point (0 - none, 1 - theS1, 2 - theS2) +//======================================================================= +static IntPatch_SpecPntType IsPoleOrSeam(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + Handle(IntSurf_LineOn2S)& theLine, + IntPatch_Point &theVertex, + const Standard_Real* const theArrPeriods, + const Standard_Real theTol3d, + Standard_Integer& theSingularSurfaceID) +{ + const Standard_Integer aNbPnts = theLine->NbPoints(); + if(aNbPnts == 0) + return IntPatch_SPntNone; + + theSingularSurfaceID = 0; + + for(Standard_Integer i = 0; i < 2; i++) + { + const Standard_Boolean isReversed = (i > 0); + const GeomAbs_SurfaceType aType = isReversed? theS2->GetType() : theS1->GetType(); + + IntPatch_SpecPntType anAddedPType = IntPatch_SPntNone; + IntSurf_PntOn2S anApexPoint; + + switch(aType) + { + case GeomAbs_Sphere: + case GeomAbs_Cone: + { + if(IntPatch_SpecialPoints:: + AddSingularPole((isReversed? theS2 : theS1), (isReversed? theS1 : theS2), + theLine->Value(aNbPnts), theTol3d, theVertex, + anApexPoint, isReversed, Standard_True)) + { + anAddedPType = IntPatch_SPntPole; + break; + } + } + case GeomAbs_Torus: + if(aType == GeomAbs_Torus) + { + if(IntPatch_SpecialPoints:: + AddCrossUVIsoPoint((isReversed? theS2 : theS1), (isReversed? theS1 : theS2), + theLine->Value(aNbPnts), theTol3d, + anApexPoint, isReversed)) + { + anAddedPType = IntPatch_SPntSeamUV; + break; + } + } + case GeomAbs_Cylinder: + theSingularSurfaceID = i + 1; + AddVertexPoint(theLine, theVertex, theArrPeriods); + return IntPatch_SPntSeamU; + + default: + break; + } + + if(anAddedPType != IntPatch_SPntNone) + { + theSingularSurfaceID = i + 1; + AddPointIntoLine(theLine, theArrPeriods, anApexPoint, &theVertex); + return anAddedPType; + } + } + + return IntPatch_SPntNone; +} -//-- Je ne sais pas faire mieux et ca m'ennerve. lbr. //======================================================================= //function : IntPatch_ALineToWLine //purpose : //======================================================================= - IntPatch_ALineToWLine::IntPatch_ALineToWLine(const IntSurf_Quadric& Quad1, - const IntSurf_Quadric& Quad2) -: - quad1(Quad1), - quad2(Quad2), - deflectionmax(0.01), - nbpointsmax(200), - type(0), - myTolParam(1.e-12), +IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Integer theNbPoints) : + myS1(theS1), + myS2(theS2), + myNbPointsInWline(theNbPoints), myTolOpenDomain(1.e-9), - myTolTransition(1.e-8) + myTolTransition(1.e-8), + myTol3D(Precision::Confusion()) { - myTol3D=Precision::Confusion(); -} -//======================================================================= -//function : IntPatch_ALineToWLine -//purpose : -//======================================================================= - IntPatch_ALineToWLine::IntPatch_ALineToWLine(const IntSurf_Quadric& Quad1, - const IntSurf_Quadric& Quad2, - const Standard_Real Deflection, - const Standard_Real , - const Standard_Integer NbMaxPoints) -: - quad1(Quad1), - quad2(Quad2), - deflectionmax(Deflection), - nbpointsmax(NbMaxPoints), - myTolParam(1.e-12), - myTolOpenDomain(1.e-9), - myTolTransition(1.e-8) -{ - myTol3D=Precision::Confusion(); - type = 0; + const GeomAbs_SurfaceType aTyps1 = theS1->GetType(); + const GeomAbs_SurfaceType aTyps2 = theS2->GetType(); + + switch(aTyps1) + { + case GeomAbs_Plane: + myQuad1.SetValue(theS1->Plane()); + break; + + case GeomAbs_Cylinder: + myQuad1.SetValue(theS1->Cylinder()); + break; + + case GeomAbs_Sphere: + myQuad1.SetValue(theS1->Sphere()); + break; + + case GeomAbs_Cone: + myQuad1.SetValue(theS1->Cone()); + break; + + case GeomAbs_Torus: + myQuad1.SetValue(theS1->Torus()); + break; + + default: + break; + } + + switch(aTyps2) + { + case GeomAbs_Plane: + myQuad2.SetValue(theS2->Plane()); + break; + case GeomAbs_Cylinder: + myQuad2.SetValue(theS2->Cylinder()); + break; + + case GeomAbs_Sphere: + myQuad2.SetValue(theS2->Sphere()); + break; + + case GeomAbs_Cone: + myQuad2.SetValue(theS2->Cone()); + break; + + case GeomAbs_Torus: + myQuad2.SetValue(theS2->Torus()); + break; + + default: + break; + } } + //======================================================================= //function : SetTol3D //purpose : @@ -157,22 +235,6 @@ static return myTolTransition; } //======================================================================= -//function : SetTolParam -//purpose : -//======================================================================= - void IntPatch_ALineToWLine::SetTolParam(const Standard_Real aTolParam) -{ - myTolParam = aTolParam; -} -//======================================================================= -//function : TolParam -//purpose : -//======================================================================= - Standard_Real IntPatch_ALineToWLine::TolParam()const -{ - return myTolParam; -} -//======================================================================= //function : SetTolOpenDomain //purpose : //======================================================================= @@ -189,1051 +251,445 @@ static return myTolOpenDomain; } //======================================================================= -//function : SetConstantParameter -//purpose : -//======================================================================= - void IntPatch_ALineToWLine::SetConstantParameter() const -{ -} -//======================================================================= -//function : SetUniformAbscissa -//purpose : -//======================================================================= - void IntPatch_ALineToWLine::SetUniformAbscissa() const -{ -} -//======================================================================= -//function : SetUniformDeflection -//purpose : -//======================================================================= - void IntPatch_ALineToWLine::SetUniformDeflection() const -{ -} -//======================================================================= //function : MakeWLine //purpose : //======================================================================= - Handle(IntPatch_WLine) IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& aline) const +void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theAline, + IntPatch_SequenceOfLine& theLines) const { Standard_Boolean included; - Standard_Real f = aline->FirstParameter(included); + Standard_Real f = theAline->FirstParameter(included); if(!included) { f+=myTolOpenDomain; } - Standard_Real l = aline->LastParameter(included); + Standard_Real l = theAline->LastParameter(included); if(!included) { l-=myTolOpenDomain; } - return(MakeWLine(aline,f,l)); + + MakeWLine(theAline, f, l, theLines); } //======================================================================= //function : MakeWLine //purpose : //======================================================================= - Handle(IntPatch_WLine) IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& aline, - const Standard_Real _firstparam, - const Standard_Real _lastparam) const +void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine, + const Standard_Real theFPar, + const Standard_Real theLPar, + IntPatch_SequenceOfLine& theLines) const { - // - Standard_Real dl, dumin, dumax, U, pv, pu1, pv1, pu2, pv2; - Standard_Real firstparam, lastparam; - Standard_Integer v, nbvtx; - Standard_Boolean TriOk; - // - firstparam = _firstparam; - lastparam = _lastparam; - // Pas Bon ... - // nbpointsmax It is the field. ( =200. by default) - dl = (lastparam - firstparam)/(Standard_Real)(nbpointsmax-1); - dumin = 0.1*dl; - dumax = 10 * dl; - // - nbvtx = aline->NbVertex(); - // - TColStd_Array1OfReal paramvertex(1,Max(nbvtx,1)), newparamvertex(1,Max(nbvtx,1)); - // - for(v = 1; v<=nbvtx; v++) { - const IntPatch_Point& aVtx = aline->Vertex(v); - pv=aVtx.ParameterOnLine(); - paramvertex(v)=pv; - newparamvertex(v)=-1.; - } - // - //-- Tri et Confusion des vertex proches - do { - TriOk = Standard_True; - for(v=2; v<=nbvtx;v++) { - if(paramvertex(v) < paramvertex(v-1)) { - pv=paramvertex(v); - paramvertex(v-1)=paramvertex(v); - paramvertex(v)=pv; - TriOk = Standard_False; - } - } - } - while(!TriOk); - // - for(v=2; v<=nbvtx;v++) { - pv=paramvertex(v); - pv1=paramvertex(v-1); - if(pv-pv1 < myTolParam) { - paramvertex(v)=pv1; - } - } - // - Standard_Integer t, nbpwline; - Standard_Real u1,v1,u2,v2, anu1, anv1, anu2, anv2; - Standard_Real aL, dl_sur_2; - gp_Pnt Pnt3d, aPnt3d1; - IntSurf_PntOn2S POn2S; - Handle(IntSurf_LineOn2S) LinOn2S; - // - LinOn2S = new IntSurf_LineOn2S; + const Standard_Integer aNbVert = theALine->NbVertex(); + const Standard_Real aTol = 2.0*myTol3D+Precision::Confusion(); + IntPatch_SpecPntType aPrePointExist = IntPatch_SPntNone; + + NCollection_Array1 aVertexParams(1, aNbVert); + NCollection_Array1 aSeqVertex(1, aNbVert); - //// Modified by jgv, 17.09.09 for OCC21255 //// - Standard_Real refpar = RealLast(), ref_u1 = 0., ref_u2 = 0.; - if (nbvtx) + //It is possible to have several vertices with equal parameters. + NCollection_Array1 hasVertexBeenChecked(1, aNbVert); + + Handle(IntSurf_LineOn2S) aLinOn2S; + Standard_Real aParameter = theFPar; + + for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++) + { + const Standard_Real aPar = theALine->Vertex(i).ParameterOnLine(); + aVertexParams(i) = aPar; + hasVertexBeenChecked(i) = Standard_False; + } + + Standard_Integer aSingularSurfaceID = 0; + Standard_Real anArrPeriods[] = { 0.0, //U1 + 0.0, //V1 + 0.0, //U2 + 0.0}; //V2 + + IntSurf::SetPeriod(myS1, myS2, anArrPeriods); + + IntSurf_PntOn2S aPrevLPoint; + + while(aParameter < theLPar) + { + Standard_Real aStep = (theLPar - aParameter) / (Standard_Real)(myNbPointsInWline - 1); + if(aStep < Epsilon(theLPar)) + break; + + Standard_Integer aNewVertID = 0; + aLinOn2S = new IntSurf_LineOn2S; + + const Standard_Real aStepMin = 0.1*aStep, aStepMax = 10.0*aStep; + + Standard_Boolean isLast = Standard_False; + Standard_Real aPrevParam = aParameter; + for(; !isLast; aParameter += aStep) { - const IntPatch_Point& FirstVertex = aline->Vertex(1); - refpar = FirstVertex.ParameterOnLine(); - FirstVertex.Parameters(ref_u1, v1, ref_u2, v2); - } - //////////////////////////////////////////////// + IntSurf_PntOn2S aPOn2S; - //----------------------------------------------------- - //-- Estimation Grossiere de la longueur de la courbe - //-- - aL=0.; - dl_sur_2=0.5*dl; - Pnt3d = aline->Value(firstparam); - for(t=0, U=firstparam+dumin; UValue(U); - aL+=Pnt3d.Distance(aPnt3d1); - Pnt3d=aPnt3d1; - } - //------------------------------------------------------ - aL/=t; - aL*=2; - //------------------------------------------------------ - //-- Calcul du premier point - //-- - //------------------------------------------------------ - //-- On reajuste firstparam et lastparam au cas ou ces - //-- valeurs sont tres proches des parametres de vertex - if(nbvtx) { - Standard_Real pvtxmin, pvtxmax; - // - pvtxmin = aline->Vertex(1).ParameterOnLine(); - pvtxmax = pvtxmin; - // - for(v=2; v<=nbvtx; v++) { - pv=aline->Vertex(v).ParameterOnLine(); - if(pvtxmin>pv){ - pvtxmin = pv; - } - if(pvtxmaxValue(firstparam); - quad1.Parameters(Pnt3d,u1,v1); - // - RefineParameters(aline, firstparam, lastparam, firstparam, 1, quad1, 10.*myTol3D, u1,v1); - // - // - quad2.Parameters(Pnt3d,u2,v2); - // - RefineParameters(aline, firstparam, lastparam, firstparam, 1, quad2, 10.*myTol3D, u2,v2); - // - - POn2S.SetValue(Pnt3d,u1,v1,u2,v2); - anu1 = u1; - anu2 = u2; - LinOn2S->Add(POn2S); - nbpwline = 1; - U = firstparam; - //------------------------------------------------------- - //-- On detecte le cas : Point de debut == vertex - //-- On affecte un parametre bidon qui sera recadre - //-- dans l insertion des vertex dans la ligne - //-- - for(v=1;v<=nbvtx;v++) { - if(newparamvertex(v)<0.) { - pv=paramvertex(v); - if((pv>=U-2.0*myTolOpenDomain) && (pv<=U+2.0*myTolOpenDomain)) { - if(pv-U > myTolParam) { - newparamvertex(v) = 1.000001; - } - else if(U-pv>myTolParam) { - newparamvertex(v) = 0.999999; - } - } - } - } - // - Standard_Real DeltaU; - // - // the loop - DeltaU=0.; - //// Modified by jgv, 17.09.09 for OCC21255 //// - Standard_Boolean Corrected = Standard_False; - //////////////////////////////////////////////// - while(UD1(UPourCalculD1,PPourCalculD1,VPourCalculD1)) { - Standard_Real NormV = VPourCalculD1.Magnitude(); - if(NormV > 1.0e-16) { - DeltaU = aL/NormV; - } - } - if(DeltaU < dumin) - DeltaU = dumin; - else if (DeltaU > dumax) - DeltaU = dumax; - UPourCalculD1+=dumin; - } - while((++NbCalculD1<10)&&(DeltaU==0.)); - // - //OCC541(apo)-> - // static //xft - Standard_Real CurvDef = deflectionmax, AngDef = CurvDef; - if(U+DeltaU < lastparam) { - DefineDU(aline,U,DeltaU,CurvDef,AngDef); - } - //<-OCC451(apo) - // - if(DeltaU==0.){ - DeltaU = (dumin+dumax)*0.5; - } - //-------------------------------------------------------- - //-- On cherche a placer un minimum de ??? Points entre - //-- 2 vertex - //-------------------------------------------------------- - pvavant = firstparam; - pvapres = lastparam; - for(v=1;v<=nbvtx;v++) { - pv=paramvertex(v); - if(pv-U > myTolParam) { - if(pvapres>pv) { - pvapres = pv; - } - } - else { - if(U-pv > myTolParam) { - if(pvavant (10.*dumin)) { - DeltaU = pvapres*0.1; - } - else { - DeltaU = dumin; - } - } - //xf - if (nbpwline==1 && nbvtx) { - Standard_Real aUnext; - // - aUnext=U+DeltaU; - pv=paramvertex(1); - if (aUnext>pv){ - DeltaU=0.5*(pv-firstparam); - } - } - //xt - //-------------------------------------------------------- - //-- Calcul des nouveaux parametres sur les vertex - //-- - for(v=1;v<=nbvtx;v++) { - if(newparamvertex(v)<0.) { - pv=paramvertex(v); - if(pv>=U && pv<(U+DeltaU) && (U+DeltaU= refpar) + if(theLPar <= aParameter) { - CorrectFirstPartOfLine(LinOn2S, ref_u1, ref_u2, anu1, anu2); - Corrected = Standard_True; + isLast = Standard_True; + if(aPrePointExist != IntPatch_SPntNone) + { + break; + } + else + { + aParameter = theLPar; + } } - //////////////////////////////////////////////// - U+=DeltaU; - if(U < lastparam) { - nbpwline++; - Pnt3d = aline->Value(U); - quad1.Parameters(Pnt3d,u1,v1); - quad2.Parameters(Pnt3d,u2,v2); - RecadreMemePeriode(u1,u2,anu1,anu2); - anu1 = u1; - anu2 = u2; - POn2S.SetValue(Pnt3d,u1,v1,u2,v2); - LinOn2S->Add(POn2S); - } - }//while(UValue(lastparam); - quad1.Parameters(Pnt3d,u1,v1); - // - RefineParameters(aline, firstparam, lastparam, lastparam, -1, quad1, 10.*myTol3D, u1,v1); - // - quad2.Parameters(Pnt3d,u2,v2); - // - RefineParameters(aline, firstparam, lastparam, lastparam, -1, quad2, 10.*myTol3D, u2,v2); - // - RecadreMemePeriode(u1,u2,anu1,anu2); - POn2S.SetValue(Pnt3d,u1,v1,u2,v2); - LinOn2S->Add(POn2S); - nbpwline++; - //// Modified by jgv, 17.09.09 for OCC21255 //// - if (!Corrected && - (lastparam >= refpar || refpar-lastparam < Precision::Confusion())) - CorrectFirstPartOfLine(LinOn2S, ref_u1, ref_u2, anu1, anu2); - //////////////////////////////////////////////// + Standard_Real aTgMagn = 0.0; + { + gp_Pnt aPnt3d; + gp_Vec aTg; + theALine->D1(aParameter, aPnt3d, aTg); + aTgMagn = aTg.Magnitude(); + Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0; + myQuad1.Parameters(aPnt3d, u1, v1); + myQuad2.Parameters(aPnt3d, u2, v2); + aPOn2S.SetValue(aPnt3d, u1, v1, u2, v2); + } - // - //----------------------------------------------------------------- - //-- Calcul de la transition de la ligne sur les surfaces --- - //----------------------------------------------------------------- - IntSurf_TypeTrans trans1,trans2; - Standard_Integer indice1; - Standard_Real dotcross; - gp_Pnt aPP0, aPP1; - // - trans1=IntSurf_Undecided; - trans2=IntSurf_Undecided; - // - indice1 = nbpwline/3; - if(indice1<=2) { - indice1 = 2; - } - // - aPP1=LinOn2S->Value(indice1).Value(); - aPP0=LinOn2S->Value(indice1-1).Value(); - // - gp_Vec tgvalid(aPP0, aPP1); - gp_Vec aNQ1=quad1.Normale(aPP0); - gp_Vec aNQ2=quad2.Normale(aPP0); - // - dotcross = tgvalid.DotCross(aNQ2, aNQ1); - if (dotcross > myTolTransition) { - trans1 = IntSurf_Out; - trans2 = IntSurf_In; - } - else if(dotcross < -myTolTransition) { - trans1 = IntSurf_In; - trans2 = IntSurf_Out; - } - //----------------------------------------------------------------- - //-- C r e a t i o n d e la W L i n e --- - //----------------------------------------------------------------- - Handle(IntPatch_WLine) wline; - // - if(aline->TransitionOnS1() == IntSurf_Touch) { - Handle(IntPatch_WLine) wlinetemp = new IntPatch_WLine(LinOn2S, - aline->IsTangent(), - aline->SituationS1(), - aline->SituationS2()); - wline = wlinetemp; - } - if(aline->TransitionOnS1() == IntSurf_Undecided) { - Handle(IntPatch_WLine) wlinetemp = new IntPatch_WLine(LinOn2S, - aline->IsTangent()); - wline = wlinetemp; - } - else { - Handle(IntPatch_WLine) wlinetemp = new IntPatch_WLine(LinOn2S, - aline->IsTangent(), - trans1, // aline->TransitionOnS1(), - trans2); //aline->TransitionOnS2()); - wline = wlinetemp; - } + if(aPrePointExist != IntPatch_SPntNone) + { + const Standard_Real aURes = Max(myS1->UResolution(myTol3D), + myS2->UResolution(myTol3D)), + aVRes = Max(myS1->VResolution(myTol3D), + myS2->VResolution(myTol3D)); - //----------------------------------------------------------------- - //-- I n s e r t i o n d e s v e r t e x --- - //----------------------------------------------------------------- - TColStd_Array1OfInteger Redir(1,Max(nbvtx,1)); - // - for(v=1;v<=nbvtx;v++) { - Redir(v) = v; - } - // - TriOk=Standard_True; - Standard_Integer tamp; - do { - TriOk = Standard_True; - for(v=2; v<=nbvtx;v++) { - if(newparamvertex(Redir(v))NbVertex(); - Standard_Boolean APointHasBeenRemoved; - // - do { - Standard_Boolean RemoveVtxo, RemoveVtx; - Standard_Integer vo, voo; - Standard_Real ponl, ponlo, aDist13, aDist23; - // - APointHasBeenRemoved = Standard_False; - RemoveVtxo = Standard_False; - RemoveVtx = Standard_False; - // - for(v=1; v<=nbvtx && !APointHasBeenRemoved; v++) { - // - if(newparamvertex(v)>=0.) { - const IntPatch_Point& Vtx = aline->Vertex(v); - ponl = Vtx.ParameterOnLine(); - const gp_Pnt& aP=Vtx.Value(); - // - for(vo=1; vo<=nbvtx && !APointHasBeenRemoved; vo++) { - if(v!=vo) { - if(newparamvertex(vo)>=0.) { - const IntPatch_Point& Vtxo = aline->Vertex(vo); - ponlo = Vtxo.ParameterOnLine(); - const gp_Pnt& aPo=Vtxo.Value(); - // - if(ponl-ponlo=0.) { - const IntPatch_Point& Vtxoo = aline->Vertex(voo); - const gp_Pnt& aPoo=Vtxoo.Value(); - // - aDist13=aP.Distance(aPoo); - // - if(aDist13<=myTol3D) { - //-- 2 vertex de meme param + un confondu geometriquement - if((Vtx.IsOnDomS1() == Vtxoo.IsOnDomS1()) && - (Vtx.IsOnDomS2() == Vtxoo.IsOnDomS2()) ) { - - if(Vtx.IsOnDomS1()) { - if(Vtx.ParameterOnArc1()==Vtxoo.ParameterOnArc1()) { - if(SameCurve(Vtxoo.ArcOnS1(),Vtx.ArcOnS1())) { //-- param on s1 ? - RemoveVtx = Standard_True; - } - } - } - if(Vtx.IsOnDomS2()) { - if(Vtx.ParameterOnArc2()==Vtxoo.ParameterOnArc2()) { - if(SameCurve(Vtxoo.ArcOnS2(),Vtx.ArcOnS2())) { - RemoveVtx = Standard_True; - } - } - else { - RemoveVtx = Standard_False; - } - } - } - // - if(RemoveVtx==Standard_False) { - // - aDist23=aPo.Distance(aPoo); - // - if(aDist23<=myTol3D) { - //-- 2 vertex de meme param + un confondu geometriquement - if((Vtxo.IsOnDomS1() == Vtxoo.IsOnDomS1())&& - (Vtxo.IsOnDomS2() == Vtxoo.IsOnDomS2()) ) { - if(Vtxo.IsOnDomS1()) { - if(Vtxo.ParameterOnArc1()==Vtxoo.ParameterOnArc1()) { - if(SameCurve(Vtxoo.ArcOnS1(),Vtxo.ArcOnS1())) { //-- param on s1 ? - RemoveVtxo = Standard_True; - } - } - } - if(Vtxo.IsOnDomS2()) { - if(Vtxo.ParameterOnArc2()==Vtxoo.ParameterOnArc2()) { - if(SameCurve(Vtxoo.ArcOnS2(),Vtxo.ArcOnS2())) { - RemoveVtxo = Standard_True; - } - } - else { - RemoveVtxo = Standard_False; - } - } - } - } - } //-- - if(RemoveVtx) { - newparamvertex(v) = -1.; - APointHasBeenRemoved = Standard_True; - } - else if(RemoveVtxo) { - newparamvertex(vo) = -1.; - APointHasBeenRemoved = Standard_True; - } - } //-- Pnt = Pntoo - } //-- voo!=v && voo!=vo - } //-- Fin boucle sur voo - } - } - } - } - } - } - }//for(v=1; v<=nbvtx && !APointHasBeenRemoved; v++) - } - while(APointHasBeenRemoved); - // - Standard_Integer ParamVtxPrecedent, refpointonwline, aIndV; - Standard_Real pvtx, approxparamonwline, aDst; - Standard_Boolean bIsApex1, bIsApex2; - // - ParamVtxPrecedent = 0; - // - for(v=1; v<=nbvtx; v++) { - aIndV=Redir(v); - pv=paramvertex(v);// parameter from ALine - pvtx = newparamvertex(aIndV); - if(pvtx>=0. && (pvtx <= nbpwline+1)) { - approxparamonwline=newparamvertex(aIndV); - refpointonwline=1; - // - IntPatch_Point NewPoint = aline->Vertex(aIndV); - // - Pnt3d = NewPoint.Value(); - quad1.Parameters(Pnt3d, u1, v1); - quad2.Parameters(Pnt3d, u2, v2); - //------------------------------------------------------- - //-- On recadre les parametres des vertex dans la bonne - - //-- periode en recadrant avec le point le plus proche - - //------------------------------------------------------- - if(approxparamonwline > nbpwline) { - refpointonwline = nbpwline-1; - } - else if(approxparamonwline < 1) { - refpointonwline = 1; - } - else { - refpointonwline = (Standard_Integer)approxparamonwline; - } - // - // - const IntSurf_PntOn2S& aP2Sx=LinOn2S->Value(refpointonwline); - aP2Sx.ParametersOnS1(anu1, anv1); - aP2Sx.ParametersOnS2(anu2, anv2); - // - bIsApex1=IsApex(quad1, v1, myTol3D); - bIsApex2=IsApex(quad2, v2, myTol3D); - // - //if (refpointonwline==1 || refpointonwline==nbpwline) { - if (bIsApex1 || bIsApex2) { - if (fabs(pv-firstparam)AddVertex(NewPoint); - } - // - else { - if(ParamVtxPrecedent==refpointonwline) { - //-- 2 vertex renseignent le meme point de la LineOn2S - //-- On insere un nv point = vtx - //-- On decale tous les vtx apres de 1 - RecadreMemePeriode(u1,u2,anu1,anu2); - POn2S.SetValue(Pnt3d,u1,v1,u2,v2); - LinOn2S->InsertBefore(refpointonwline+1, POn2S); - nbpwline++; - NewPoint.SetParameter(refpointonwline+1); - NewPoint.SetParameters(u1,v1,u2,v2); - wline->AddVertex(NewPoint); - ParamVtxPrecedent = refpointonwline+1; - // - Standard_Integer vv=v+1; - for(; vv<=nbvtx; vv++) { - if(newparamvertex(Redir(vv))!=-1.) { - newparamvertex(Redir(vv))=newparamvertex(Redir(vv))+1.; - } - } - } - // - else { - RecadreMemePeriode(u1,u2, anu1, anu2); - NewPoint.SetParameter(refpointonwline); - // - NewPoint.SetParameters(u1, v1, u2, v2); - wline->AddVertex(NewPoint); - ParamVtxPrecedent = refpointonwline; - } - } - } - } - // - pu1=0.; - pv1=0.; - pu2=0.; - pv2=0.; - // - switch(quad1.TypeQuadric()) { - case GeomAbs_Cylinder: - case GeomAbs_Cone: - case GeomAbs_Sphere: - pu1=M_PI+M_PI; - break; - case GeomAbs_Torus: - pu1=pv1=M_PI+M_PI; - break; - default: - break; - } - switch(quad2.TypeQuadric()) { - case GeomAbs_Cylinder: - case GeomAbs_Cone: - case GeomAbs_Sphere: - pu2=M_PI+M_PI; - break; - case GeomAbs_Torus: - pu2=pv2=M_PI+M_PI; - break; - default: - break; - } - wline->SetPeriod(pu1,pv1,pu2,pv2); - - wline->ComputeVertexParameters(myTol3D); - return(wline); -} -//======================================================================= -//function : DefineDU -//purpose : -//======================================================================= -gp_Pnt DefineDU(const Handle(IntPatch_ALine)& aline, - const Standard_Real U, - Standard_Real& DU, - const Standard_Real CurvDef, - const Standard_Real AngDef) -{ - gp_Pnt P1 = aline->Value(U), P2, P3; - gp_Vec V13, V12, V23; - Standard_Real dU = DU/2.0, curvDef, angDef, m1, m2, m3; - for(;;) { //According to class TangentialDeflection from GCPnts - P2=aline->Value(U+dU); P3=aline->Value(U+DU); - V13 = P3.XYZ().Subtracted(P1.XYZ()); m1 = V13.Magnitude(); - V12 = P2.XYZ().Subtracted(P1.XYZ()); m2 = V12.Magnitude(); - V23 = P3.XYZ().Subtracted(P2.XYZ()); m3 = V23.Magnitude(); - if(m1 < CurvDef || m2 < CurvDef || m3 < CurvDef) break; - curvDef = Abs(V13.Angle(V12)); - angDef = Abs(V13.Angle(V23)); - if(curvDef < CurvDef && angDef < AngDef) break; - DU = dU; dU /= 2.0; - } - return P3; -} -//======================================================================= -//function : SameCurve -//purpose : -//======================================================================= -Standard_Boolean SameCurve(const Handle(Adaptor2d_HCurve2d)& C1,const Handle(Adaptor2d_HCurve2d)& C2) -{ - Standard_Real C1f = C1->FirstParameter(); - Standard_Real C2f = C2->FirstParameter(); - if(C1f!=C2f) return(Standard_False); - Standard_Real C1l = C1->LastParameter(); - Standard_Real C2l = C2->LastParameter(); - if(C1l!=C2l) return(Standard_False); - Standard_Real u=0.3*C1f+0.7*C1l; - gp_Pnt2d P1 = C1->Value(u); - gp_Pnt2d P2 = C2->Value(u); - if(P1.X()!=P2.X()) return(Standard_False); - if(P1.Y()!=P2.Y()) return(Standard_False); - return(Standard_True); -} -//======================================================================= -//function : RecadreMemePeriode -//purpose : -//======================================================================= -void RecadreMemePeriode(Standard_Real& u1, - Standard_Real& u2, - const Standard_Real anu1, - const Standard_Real anu2) -{ - // - while(anu1-u1 > 5.0) { - u1+=M_PI+M_PI; - } - while(u1-anu1 > 5.0) { - // - /* - if (!bBothCylinders) {//cfe900/H6 - // this check on Cylinder/Cylinder intersection is probably - // because of pbs with ALine on it. - // For other Quadrics there was no pbs found during - // grid tests. - // (it is necessary to see ...IntCyCy(...) for details). - // - // In any case the pb does not deal with apex problem. - // - if (u1-M_PI-M_PI<0.) { - break; - } - } - */ - // - u1-=M_PI+M_PI; - } - while(anu2-u2 > 5.0) { - u2+=M_PI+M_PI; - } - while(u2-anu2 > 5.0) { - // - /* - if (!bBothCylinders) {//cfe900/H6 - if (u2-M_PI-M_PI<0.) { - break; - } - } - */ - // - u2-=M_PI+M_PI; - } -} + const Standard_Real aTol2d = (aPrePointExist == IntPatch_SPntPole) ? -1.0 : + (aPrePointExist == IntPatch_SPntSeamV)? aVRes : + (aPrePointExist == IntPatch_SPntSeamUV)? Max(aURes, aVRes) : aURes; -//======================================================================= -//function : CorrectFirstPartOfLine -//purpose : -//======================================================================= -void CorrectFirstPartOfLine(Handle(IntSurf_LineOn2S)& LinOn2S, - const Standard_Real ref_u1, - const Standard_Real ref_u2, - Standard_Real& new_u1, - Standard_Real& new_u2) -{ - Standard_Integer nbp = LinOn2S->NbPoints(); - Standard_Real u1, v1, u2, v2, OffsetOnS1, OffsetOnS2; + IntSurf_PntOn2S aRPT = aPOn2S; - IntSurf_PntOn2S aPoint = LinOn2S->Value(nbp); - aPoint.Parameters(u1, v1, u2, v2); + if (aPrePointExist == IntPatch_SPntPole) + { + Standard_Real aPrt = 0.5*(aPrevParam + theLPar); + for (Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++) + { + const Standard_Real aParam = aVertexParams(i); - new_u1 = u1; - new_u2 = u2; - RecadreMemePeriode(new_u1, new_u2, ref_u1, ref_u2); - OffsetOnS1 = new_u1 - u1; - OffsetOnS2 = new_u2 - u2; - if (Abs(OffsetOnS1) > 1. || Abs(OffsetOnS2) > 1.) //recadre on n*2*PI is done + if (aParam <= aPrevParam) + continue; + + aPrt = 0.5*(aParam + aPrevParam); + break; + } + + const gp_Pnt aPnt3d(theALine->Value(aPrt)); + Standard_Real u1, v1, u2, v2; + myQuad1.Parameters(aPnt3d, u1, v1); + myQuad2.Parameters(aPnt3d, u2, v2); + aRPT.SetValue(aPnt3d, u1, v1, u2, v2); + + if (aPOn2S.IsSame(aPrevLPoint, Max(Precision::Approximation(), aTol))) + { + //Set V-parameter as precise value found on the previous step. + if (aSingularSurfaceID == 1) + { + aPOn2S.ParametersOnS1(u2, v2); + aPOn2S.SetValue(Standard_True, u1, v2); + } + else //if (aSingularSurfaceID == 2) + { + aPOn2S.ParametersOnS2(u1, v1); + aPOn2S.SetValue(Standard_False, u2, v1); + } + } + } + + if(IntPatch_SpecialPoints:: + ContinueAfterSpecialPoint(myS1, myS2, aRPT, + aPrePointExist, aTol2d, + aPrevLPoint, Standard_False)) + { + AddPointIntoLine(aLinOn2S, anArrPeriods, aPrevLPoint); + } + else if(aParameter == theLPar) + {// Strictly equal!!! + break; + } + } + + aPrePointExist = IntPatch_SPntNone; + + Standard_Integer aVertexNumber = -1; + for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++) + { + if(hasVertexBeenChecked(i)) + continue; + + const Standard_Real aParam = aVertexParams(i); + if( ((aPrevParam < aParam) && (aParam <= aParameter)) || + ((aPrevParam == aParameter) && (aParam == aParameter))) + { + aVertexNumber = i; + break; + } + } + + aPrevParam = aParameter; + + if(aVertexNumber < 0) + { + StepComputing(theALine, aPOn2S, theLPar, aParameter, aTgMagn, + aStepMin, aStepMax, myTol3D, aStep); + AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S); + aPrevLPoint = aPOn2S; + continue; + } + + IntPatch_Point aVtx = theALine->Vertex(aVertexNumber); + const Standard_Real aNewVertexParam = aLinOn2S->NbPoints() + 1; + + //ATTENTION!!! + // IsPoleOrSeam inserts new point in aLinOn2S if aVtx respects + //to some special point. Otherwise, aLinOn2S is not changed. + + aPrePointExist = IsPoleOrSeam(myS1, myS2, aLinOn2S, aVtx, + anArrPeriods, aTol, aSingularSurfaceID); + + const Standard_Real aCurVertParam = aVtx.ParameterOnLine(); + if(aPrePointExist != IntPatch_SPntNone) + { + aPrevParam = aParameter = aCurVertParam; + } + else + { + if(aVtx.Tolerance() > aTol) + { + aVtx.SetValue(aPOn2S); + AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S); + } + else + { + AddVertexPoint(aLinOn2S, aVtx, anArrPeriods); + } + } + + aPrevLPoint = aPOn2S = aLinOn2S->Value(aLinOn2S->NbPoints()); + + { + Standard_Boolean isFound = Standard_False; + const Standard_Real aSqTol = aTol*aTol; + const gp_Pnt aP1(theALine->Value(aCurVertParam)); + const IntSurf_PntOn2S& aVertP2S = aVtx.PntOn2S(); + const Standard_Real aVertToler = aVtx.Tolerance(); + + for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++) + { + if(hasVertexBeenChecked(i)) + continue; + + const gp_Pnt aP2(theALine->Value(aVertexParams(i))); + + if(aP1.SquareDistance(aP2) < aSqTol) + { + IntPatch_Point aVtx = theALine->Vertex(i); + aVtx.SetValue(aVertP2S); + aVtx.SetTolerance(aVertToler); + aVtx.SetParameter(aNewVertexParam); + aSeqVertex(++aNewVertID) = aVtx; + hasVertexBeenChecked(i) = Standard_True; + isFound = Standard_True; + } + else if(isFound) + { + break; + } + } + } + + if(aPrePointExist != IntPatch_SPntNone) + break; + }//for(; !isLast; aParameter += aStep) + + if(aLinOn2S->NbPoints() < 2) { - Standard_Integer i; - for (i = 1; i <= nbp; i++) - { - aPoint = LinOn2S->Value(i); - aPoint.Parameters(u1, v1, u2, v2); - LinOn2S->SetUV( i, Standard_True, u1 + OffsetOnS1, v1 ); - LinOn2S->SetUV( i, Standard_False, u2 + OffsetOnS2, v2 ); - } + aParameter += aStep; + continue; } -} -// -//======================================================================= -//function : IsApex -//purpose : -//======================================================================= -Standard_Boolean IsApex(const IntSurf_Quadric& aQuadric, - const Standard_Real aVx, - const Standard_Real aTol3D) - -{ - Standard_Boolean bFlag; - Standard_Real aHalfPi, aEpsilon; - GeomAbs_SurfaceType aType; - // - bFlag=Standard_False; - // - aType=aQuadric.TypeQuadric(); - if (!(aType==GeomAbs_Cone || aType==GeomAbs_Sphere)) { - return bFlag; - } - // - aEpsilon=Epsilon(10.);//1.77e-15 - // - // apex on the Sphere - if(aType==GeomAbs_Sphere) { - aHalfPi=0.5*M_PI; - if (fabs(aVx-aHalfPi)Value(aTx); - // - aDst=aPx.Distance(aPap); - if(aDst>aTol3D) {// nothing to do - return; - } - // - aPLim.SetY(aVx); - aLLim.SetLocation(aPLim); - // - } - // - // apex on the Sphere - if(aType==GeomAbs_Sphere) { - aHalfPi=0.5*M_PI; - // - if (fabs(aVx-aHalfPi)Value(aT1); - aQuadric.Parameters(aP1, aU1, aV1); - - if(fabs(aU1) > fabs(aU1 - 2.*M_PI)) { - aUx = 2.*M_PI; - } - else { - aUx = 0.; - } + //----------------------------------------------------------------- + //-- Computation of transitions of the line on two surfaces --- + //----------------------------------------------------------------- + IntSurf_TypeTrans trans1,trans2; + { + Standard_Integer indice1; + Standard_Real dotcross; + gp_Pnt aPP0, aPP1; + // + trans1=IntSurf_Undecided; + trans2=IntSurf_Undecided; + // + indice1 = aLinOn2S->NbPoints()/3; + if(indice1<=2) { + indice1 = 2; } - - return; + // + aPP1=aLinOn2S->Value(indice1).Value(); + aPP0=aLinOn2S->Value(indice1-1).Value(); + // + gp_Vec tgvalid(aPP0, aPP1); + gp_Vec aNQ1 = myQuad1.Normale(aPP0); + gp_Vec aNQ2 = myQuad2.Normale(aPP0); + // + dotcross = tgvalid.DotCross(aNQ2, aNQ1); + if (dotcross > myTolTransition) { + trans1 = IntSurf_Out; + trans2 = IntSurf_In; + } + else if(dotcross < -myTolTransition) { + trans1 = IntSurf_In; + trans2 = IntSurf_Out; + } } - // - aPLim.SetY(aLimV); - aLLim.SetLocation(aPLim); - } - // - // aT1, aT2 - // - // Try to find aT1, aT2 taking into acc 3D Tolerance - bFound=FindNearParameter(aALine, aTx, iDir, aTol3D, aT1); - if (bFound) { - bFound=FindNearParameter(aALine, aT1, iDir, aTol3D, aT2); - } - if (!bFound) { - // Assign aT1, aT2 by some values - dT=aEpsT*(aTe-aTb); - if (iDir<0) { - dT=-dT; - } - aT1=aTx+dT; - aT2=aT1+dT; - } - // - aP1=aALine->Value(aT1); - aQuadric.Parameters(aP1, aU1, aV1); - aP2D1.SetCoord(aU1, aV1); - // - aP2=aALine->Value(aT2); - aQuadric.Parameters(aP2, aU2, aV2); - aP2D2.SetCoord(aU2, aV2); - // - gp_Vec2d aV12(aP2D1, aP2D2); - if(aV12.SquareMagnitude() <= aEpsilon) { - return; - } - gp_Lin2d aL12(aP2D1, aV12); - // - aAI.Perform(aLLim, aL12); - bIsDone=aAI.IsDone(); - if (!bIsDone) { - return; - } - bIsEmpty=aAI.IsEmpty(); - if (bIsEmpty) { - return; - } - aNbPoints=aAI.NbPoints(); - if (!aNbPoints) { - return; - } - bParallel=aAI.ParallelElements(); - if (bParallel) { - return; - } - const IntAna2d_IntPoint& aIAPnt=aAI.Point(1); - const gp_Pnt2d& aP2D=aIAPnt.Value(); - aUx=aP2D.X(); + //----------------------------------------------------------------- + //-- W L i n e c r e a t i o n --- + //----------------------------------------------------------------- + Handle(IntPatch_WLine) aWLine; + // + if(theALine->TransitionOnS1() == IntSurf_Touch) { + aWLine = new IntPatch_WLine(aLinOn2S, + theALine->IsTangent(), + theALine->SituationS1(), + theALine->SituationS2()); + } + if(theALine->TransitionOnS1() == IntSurf_Undecided) { + aWLine = new IntPatch_WLine(aLinOn2S, theALine->IsTangent()); + } + else { + aWLine = new IntPatch_WLine(aLinOn2S, theALine->IsTangent(), + trans1, // aline->TransitionOnS1(), + trans2); //aline->TransitionOnS2()); + } + + for(Standard_Integer i = aSeqVertex.Lower(); i <= aNewVertID; i++) + { + const IntPatch_Point& aVtx = aSeqVertex(i); + aWLine->AddVertex(aVtx); + } + + aWLine->SetPeriod(anArrPeriods[0],anArrPeriods[1],anArrPeriods[2],anArrPeriods[3]); + + aWLine->ComputeVertexParameters(myTol3D); + + aWLine->EnablePurging(Standard_False); + theLines.Append(aWLine); + }//while(aParameter < theLPar) } + //======================================================================= -//function : FindNearParameter +//function : CheckDeflection +//purpose : Returns: +// -1 - step is too small +// 0 - step is normal +// +1 - step is too big +//======================================================================= +Standard_Integer IntPatch_ALineToWLine::CheckDeflection(const gp_XYZ& theMidPt, + const Standard_Real theMaxDeflection) const +{ + Standard_Real aDist = Abs(myQuad1.Distance(theMidPt)); + if(aDist > theMaxDeflection) + return 1; + + aDist = Max(Abs(myQuad2.Distance(theMidPt)), aDist); + + if(aDist > theMaxDeflection) + return 1; + + if((aDist + aDist) < theMaxDeflection) + return -1; + + return 0; +} + +//======================================================================= +//function : StepComputing //purpose : //======================================================================= -Standard_Boolean FindNearParameter(const Handle(IntPatch_ALine)& aALine, - const Standard_Real aTx, - const Standard_Integer iDir, - const Standard_Real aTol3D, - Standard_Real& aT1) +Standard_Boolean IntPatch_ALineToWLine:: + StepComputing(const Handle(IntPatch_ALine)& theALine, + const IntSurf_PntOn2S& thePOn2S, + const Standard_Real theLastParOfAline, + const Standard_Real theCurParam, + const Standard_Real theTgMagnitude, + const Standard_Real theStepMin, + const Standard_Real theStepMax, + const Standard_Real theMaxDeflection, + Standard_Real& theStep) const { - Standard_Boolean bFound; - Standard_Real aX, aY, aZ; - gp_Pnt aPx, aP1; - gp_Vec aVx; - // - aT1=0.; - // - bFound=aALine->D1(aTx, aPx, aVx); - if(!bFound){ - return bFound; + if(theTgMagnitude < Precision::Confusion()) + return Standard_False; + + const Standard_Real anEps = myTol3D; + + //Indeed, 1.0e+15 < 2^50 < 1.0e+16. Therefore, + //if we apply bisection method to the range with length + //1.0e+6 then we will be able to find solution with max error ~1.0e-9. + const Standard_Integer aNbIterMax = 50; + + const Standard_Real aNotFilledRange = theLastParOfAline - theCurParam; + Standard_Real aMinStep = theStepMin, aMaxStep = Min(theStepMax, aNotFilledRange); + + if(aMinStep > aMaxStep) + { + theStep = aMaxStep; + return Standard_True; } - gp_Dir aDx(aVx); - if (iDir<0) { - aDx.Reverse(); + + const Standard_Real aR = IntPatch_PointLine:: + CurvatureRadiusOfIntersLine(myS1, myS2, thePOn2S); + + if(aR < 0.0) + { + return Standard_False; } - aX=aPx.X()+aDx.X()*aTol3D; - aY=aPx.Y()+aDx.Y()*aTol3D; - aZ=aPx.Z()+aDx.Z()*aTol3D; - aP1.SetCoord(aX, aY, aZ); - // - bFound=aALine->FindParameter(aP1, aT1); - // - return bFound; + else + { + //The 3D-step is defined as length of the tangent to the osculating circle + //by the condition that the distance from end point of the tangent to the + //circle is no greater than anEps. theStep is the step in + //parameter space of intersection curve (must be converted from 3D-step). + + theStep = Min(sqrt(anEps*(2.0*aR + anEps))/theTgMagnitude, aMaxStep); + theStep = Max(theStep, aMinStep); + } + + //The step value has been computed for osculating circle. + //Now it should be checked for real intersection curve + //and is made more precise in case of necessity. + + Standard_Integer aNbIter = 0; + do + { + aNbIter++; + + const gp_XYZ& aP1 = thePOn2S.Value().XYZ(); + const gp_XYZ aP2(theALine->Value(theCurParam + theStep).XYZ()); + const Standard_Integer aStatus = CheckDeflection(0.5*(aP1 + aP2), theMaxDeflection); + + if(aStatus == 0) + break; + + if(aStatus < 0) + { + aMinStep = theStep; + } + else //if(aStatus > 0) + { + aMaxStep = theStep; + } + + theStep = 0.5*(aMinStep + aMaxStep); + } + while(((aMaxStep - aMinStep) > Precision::PConfusion()) && (aNbIter <= aNbIterMax)); + + if(aNbIter > aNbIterMax) + return Standard_False; + + return Standard_True; } - diff --git a/src/IntPatch/IntPatch_ALineToWLine.hxx b/src/IntPatch/IntPatch_ALineToWLine.hxx index eb88c2727e..815dd79ca0 100644 --- a/src/IntPatch/IntPatch_ALineToWLine.hxx +++ b/src/IntPatch/IntPatch_ALineToWLine.hxx @@ -17,18 +17,15 @@ #ifndef _IntPatch_ALineToWLine_HeaderFile #define _IntPatch_ALineToWLine_HeaderFile -#include +#include +#include #include #include +#include -#include -#include -#include -class IntSurf_Quadric; -class IntPatch_WLine; +class Adaptor3d_HSurface; class IntPatch_ALine; - - +class IntSurf_PntOn2S; class IntPatch_ALineToWLine { @@ -36,14 +33,10 @@ public: DEFINE_STANDARD_ALLOC - - Standard_EXPORT IntPatch_ALineToWLine(const IntSurf_Quadric& Quad1, const IntSurf_Quadric& Quad2); - - Standard_EXPORT IntPatch_ALineToWLine(const IntSurf_Quadric& Quad1, const IntSurf_Quadric& Quad2, const Standard_Real Deflection, const Standard_Real PasMaxUV, const Standard_Integer NbMaxPoints); - - Standard_EXPORT void SetTolParam (const Standard_Real aT); - - Standard_EXPORT Standard_Real TolParam() const; + //! Constructor + Standard_EXPORT IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Integer theNbPoints = 200); Standard_EXPORT void SetTolOpenDomain (const Standard_Real aT); @@ -57,46 +50,57 @@ public: Standard_EXPORT Standard_Real Tol3D() const; - Standard_EXPORT void SetConstantParameter() const; + //! Converts aline to the set of Walking-lines and adds + //! them in theLines. + Standard_EXPORT void MakeWLine (const Handle(IntPatch_ALine)& aline, + IntPatch_SequenceOfLine& theLines) const; - Standard_EXPORT void SetUniformAbscissa() const; - - Standard_EXPORT void SetUniformDeflection() const; - - Standard_EXPORT Handle(IntPatch_WLine) MakeWLine (const Handle(IntPatch_ALine)& aline) const; - - Standard_EXPORT Handle(IntPatch_WLine) MakeWLine (const Handle(IntPatch_ALine)& aline, const Standard_Real paraminf, const Standard_Real paramsup) const; - - - + //! Converts aline (limitted by paraminf and paramsup) to the set of + //! Walking-lines and adds them in theLines. + Standard_EXPORT void MakeWLine (const Handle(IntPatch_ALine)& aline, + const Standard_Real paraminf, + const Standard_Real paramsup, + IntPatch_SequenceOfLine& theLines) const; protected: + //! Computes step value to construct point-line. The step depends on + //! the local curvature of the intersection line computed in thePOn2S. + //! theTgMagnitude is the magnitude of tangent vector to the intersection + //! line (in the point thePOn2S). + //! Computed step is always in the range [theStepMin, theStepMax]. + //! Returns FALSE if the step cannot be computed. In this case, its value + //! will not be changed. + Standard_EXPORT Standard_Boolean StepComputing(const Handle(IntPatch_ALine)& theALine, + const IntSurf_PntOn2S& thePOn2S, + const Standard_Real theLastParOfAline, + const Standard_Real theCurParam, + const Standard_Real theTgMagnitude, + const Standard_Real theStepMin, + const Standard_Real theStepMax, + const Standard_Real theMaxDeflection, + Standard_Real& theStep) const; + Standard_EXPORT Standard_Integer CheckDeflection(const gp_XYZ& theMidPt, + const Standard_Real theMaxDeflection) const; private: + Handle(Adaptor3d_HSurface) myS1; + Handle(Adaptor3d_HSurface) myS2; + IntSurf_Quadric myQuad1; + IntSurf_Quadric myQuad2; - IntSurf_Quadric quad1; - IntSurf_Quadric quad2; - Standard_Real deflectionmax; - Standard_Integer nbpointsmax; - Standard_Integer type; - Standard_Real myTolParam; + //! Approximate number of points in resulting + //! WLine (precise number of points is computed + //! by the algorithms) + Standard_Integer myNbPointsInWline; Standard_Real myTolOpenDomain; Standard_Real myTolTransition; Standard_Real myTol3D; - - }; - - - - - - #endif // _IntPatch_ALineToWLine_HeaderFile diff --git a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx index 3a9982d308..5c270f05ff 100644 --- a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx +++ b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx @@ -14,63 +14,34 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include -#include #include #include +#include #include -#include -#include -#include +#include #include #include -#include -#include +#include #include -#include -#include +#include #include #include #include -#include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #ifndef OCCT_DEBUG #define No_Standard_RangeError #define No_Standard_OutOfRange #endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLine, const Standard_Boolean IsReversed, const IntSurf_Quadric& theQuad, @@ -108,24 +79,18 @@ static const Standard_Real theToler2D, const Standard_Real thePeriod); -enum PrePoint_Type -{ - PrePoint_NONE, - PrePoint_SEAMU, - PrePoint_SEAMV, - PrePoint_SEAMUV, - PrePoint_POLESEAMU, - PrePoint_POLE -}; - -static PrePoint_Type IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQSurf, - const Handle(IntSurf_LineOn2S)& theLine, - const Standard_Boolean IsReversed, - const Standard_Integer theRefIndex, - const Standard_Real theDeltaMax) +//======================================================================= +//function : IsSeamOrPole +//purpose : +//======================================================================= +static IntPatch_SpecPntType IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(IntSurf_LineOn2S)& theLine, + const Standard_Boolean IsReversed, + const Standard_Integer theRefIndex, + const Standard_Real theDeltaMax) { if((theRefIndex < 1) || (theRefIndex >= theLine->NbPoints())) - return PrePoint_NONE; + return IntPatch_SPntNone; //Parameters on Quadric and on parametric for reference point Standard_Real aUQRef, aVQRef, aUPRef, aVPRef; @@ -147,151 +112,38 @@ static PrePoint_Type IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQSurf, const Standard_Real aDeltaU = Abs(aUQRef - aUQNext); if((aType != GeomAbs_Torus) && (aDeltaU < theDeltaMax)) - return PrePoint_NONE; + return IntPatch_SPntNone; switch(aType) { case GeomAbs_Cylinder: - return PrePoint_SEAMU; + return IntPatch_SPntSeamU; case GeomAbs_Torus: { const Standard_Real aDeltaV = Abs(aVQRef - aVQNext); if((aDeltaU >= theDeltaMax) && (aDeltaV >= theDeltaMax)) - return PrePoint_SEAMUV; + return IntPatch_SPntSeamUV; if(aDeltaU >= theDeltaMax) - return PrePoint_SEAMU; + return IntPatch_SPntSeamU; if(aDeltaV >= theDeltaMax) - return PrePoint_SEAMV; + return IntPatch_SPntSeamV; } break; case GeomAbs_Sphere: case GeomAbs_Cone: - return PrePoint_POLESEAMU; + return IntPatch_SPntPoleSeamU; default: break; } - return PrePoint_NONE; + return IntPatch_SPntNone; } -// The function for searching intersection point, which -// lies in the seam-edge of the quadric definetely. -class FuncPreciseSeam: public math_FunctionSetWithDerivatives -{ -public: - FuncPreciseSeam(const Handle(Adaptor3d_HSurface)& theQSurf, const Handle(Adaptor3d_HSurface)& thePSurf, const Standard_Boolean isTheUSeam): myQSurf(theQSurf), myPSurf(thePSurf), myIsUSeam(isTheUSeam) {}; - - Standard_EXPORT virtual Standard_Integer NbVariables() const - { - return 3; - }; - - Standard_EXPORT virtual Standard_Integer NbEquations() const - { - return 3; - } - - Standard_EXPORT virtual Standard_Boolean Value (const math_Vector& theX, math_Vector& theF) - { - try - { - const Standard_Integer anIndX = theX.Lower(), anIndF = theF.Lower(); - const gp_Pnt aP1(myPSurf->Value(theX(anIndX), theX(anIndX+1))); - const gp_Pnt aP2(myIsUSeam? myQSurf->Value(0.0, theX(anIndX+2)) : myQSurf->Value(theX(anIndX+2), 0.0)); - - (aP1.XYZ()-aP2.XYZ()).Coord(theF(anIndF), theF(anIndF+1), theF(anIndF+2)); - } - catch(Standard_Failure) - { - return Standard_False; - } - - return Standard_True; - }; - - Standard_EXPORT virtual Standard_Boolean Derivatives (const math_Vector& theX, math_Matrix& theD) - { - try - { - const Standard_Integer anIndX = theX.Lower(), anIndRD = theD.LowerRow(), anIndCD = theD.LowerCol(); - gp_Pnt aPt; - gp_Vec aD1u, aD1v, aD2u, aD2v; - myPSurf->D1(theX(anIndX), theX(anIndX+1), aPt, aD1u, aD1v); - if(myIsUSeam) - myQSurf->D1(0.0, theX(anIndX+2), aPt, aD2u, aD2v); - else - myQSurf->D1(theX(anIndX+2), 0.0, aPt, aD2u, aD2v); - - // d/dX1 - aD1u.Coord(theD(anIndRD, anIndCD), theD(anIndRD+1, anIndCD), theD(anIndRD+2, anIndCD)); - - // d/dX1 - aD1v.Coord(theD(anIndRD, anIndCD+1), theD(anIndRD+1, anIndCD+1), theD(anIndRD+2, anIndCD+1)); - - // d/dX3 - if(myIsUSeam) - aD2v.Reversed().Coord(theD(anIndRD, anIndCD+2), theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2)); - else - aD2u.Reversed().Coord(theD(anIndRD, anIndCD+2), theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2)); - } - catch(Standard_Failure) - { - return Standard_False; - } - - return Standard_True; - }; - - Standard_EXPORT virtual Standard_Boolean Values (const math_Vector& theX, math_Vector& theF, math_Matrix& theD) - { - try - { - const Standard_Integer anIndX = theX.Lower(), anIndF = theF.Lower(), anIndRD = theD.LowerRow(), anIndCD = theD.LowerCol(); - gp_Pnt aP1, aP2; - gp_Vec aD1u, aD1v, aD2u, aD2v; - myPSurf->D1(theX(anIndX), theX(anIndX+1), aP1, aD1u, aD1v); - if(myIsUSeam) - myQSurf->D1(0.0, theX(anIndX+2), aP2, aD2u, aD2v); - else - myQSurf->D1(theX(anIndX+2), 0.0, aP2, aD2u, aD2v); - - //Value - (aP1.XYZ()-aP2.XYZ()).Coord(theF(anIndF), theF(anIndF+1), theF(anIndF+2)); - - // d/dX1 - aD1u.Coord(theD(anIndRD, anIndCD), theD(anIndRD+1, anIndCD), theD(anIndRD+2, anIndCD)); - - // d/dX1 - aD1v.Coord(theD(anIndRD, anIndCD+1), theD(anIndRD+1, anIndCD+1), theD(anIndRD+2, anIndCD+1)); - - // d/dX3 - if(myIsUSeam) - aD2v.Reversed().Coord(theD(anIndRD, anIndCD+2), theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2)); - else - aD2u.Reversed().Coord(theD(anIndRD, anIndCD+2), theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2)); - } - catch(Standard_Failure) - { - return Standard_False; - } - - return Standard_True; - } - -protected: - FuncPreciseSeam operator=(FuncPreciseSeam&); - -private: - const Handle(Adaptor3d_HSurface)& myQSurf; - const Handle(Adaptor3d_HSurface)& myPSurf; - const Standard_Boolean myIsUSeam; -}; - //======================================================================= //function : IntPatch_ImpPrmIntersection //purpose : @@ -2622,7 +2474,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin // build WLine parts (if any) Standard_Boolean flNextLine = Standard_True; Standard_Boolean hasBeenDecomposed = Standard_False; - PrePoint_Type aPrePointExist = PrePoint_NONE; + IntPatch_SpecPntType aPrePointExist = IntPatch_SPntNone; IntSurf_PntOn2S PrePoint; while(flNextLine) @@ -2643,81 +2495,19 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin if(aPrePointExist) { - //The last point of the line is the pole of the quadric. - //Therefore, Walking-line has been broken in this point. - //However, new line must start from this point. Here we must - //find its 2D-coordinates. - - //For sphere and cone, some intersection point is satisfied to the system - // \cos(U_{q}) = S_{x}(U_{s},V_{s})/F(V_{q}) - // \sin(U_{q}) = S_{y}(U_{s},V_{s})/F(V_{q}) - - //where - // @S_{x}@, @S_{y}@ are X and Y-coordinates of thePSurf; - // @U_{s}@ and @V_{s}@ are UV-parameters on thePSurf; - // @U_{q}@ and @V_{q}@ are UV-parameters on theQSurf; - // @F(V_{q}) @ is some function, which value independs on @U_{q}@ - // (form of this function depends on the type of the quadric). - - //When we go through the pole, the function @F(V_{q}) @ changes sign. - //Therefore, some cases are possible, when only @\cos(U_{q}) @ or - //only @ \sin(U_{q}) @ change sign. - - //Consequently, when the line goes throug the pole, @U_{q}@ can be - //changed on @\pi /2 @ (but not less). - - //Here, we forbid "jumping" between two neighbor Walking-point - //with step greater than pi/4 - const Standard_Real aPeriod = M_PI_2, aHalfPeriod = M_PI_4; const IntSurf_PntOn2S& aRefPt = aSSLine->Value(aFindex); const Standard_Real aURes = theQSurf->UResolution(theArcTol), - aVRes = theQSurf->UResolution(theArcTol); + aVRes = theQSurf->VResolution(theArcTol); - const Standard_Real aTol2d = (aPrePointExist == PrePoint_POLE) ? 0.0 : - (aPrePointExist == PrePoint_SEAMV)? aVRes : - (aPrePointExist == PrePoint_SEAMUV)? Max(aURes, aVRes) : aURes; + const Standard_Real aTol2d = (aPrePointExist == IntPatch_SPntPole) ? -1.0 : + (aPrePointExist == IntPatch_SPntSeamV)? aVRes : + (aPrePointExist == IntPatch_SPntSeamUV)? Max(aURes, aVRes) : aURes; - if(!PrePoint.IsSame(aRefPt, Precision::Confusion(), aTol2d)) + if(IntPatch_SpecialPoints::ContinueAfterSpecialPoint(theQSurf, thePSurf, aRefPt, + aPrePointExist, aTol2d, + PrePoint, IsReversed)) { - Standard_Real aURef = 0.0, aVRef = 0.0; - Standard_Real aUquad = 0.0, aVquad = 0.0; - - //Take parameters on quadric - if(IsReversed) - { - PrePoint.ParametersOnS2(aUquad, aVquad); - aRefPt.ParametersOnS2(aURef, aVRef); - } - else - { - PrePoint.ParametersOnS1(aUquad, aVquad); - aRefPt.ParametersOnS1(aURef, aVRef); - } - - if(theQSurf->IsUPeriodic()) - { - Standard_Real aDeltaPar = aURef-aUquad; - const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aUquad += anIncr; - aDeltaPar = aURef-aUquad; - } - } - - if(theQSurf->IsVPeriodic()) - { - Standard_Real aDeltaPar = aVRef-aVquad; - const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aVquad += anIncr; - aDeltaPar = aVRef-aVquad; - } - } - - PrePoint.SetValue(!IsReversed, aUquad, aVquad); sline->Add(PrePoint); } else @@ -2727,7 +2517,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin } } - aPrePointExist = PrePoint_NONE; + aPrePointExist = IntPatch_SPntNone; // analyze other points for(Standard_Integer k = aFindex; k <= aLindex; k++) @@ -2750,90 +2540,49 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin aPrePointExist = IsSeamOrPole(theQSurf, aSSLine, IsReversed, k-1, aDeltaUmax); - if(aPrePointExist != PrePoint_NONE) + if(aPrePointExist != IntPatch_SPntNone) { aBindex = k; isDecomposited = Standard_True; //// - const Standard_Real aPeriod = M_PI+M_PI, aHalfPeriod = M_PI; const IntSurf_PntOn2S& aRefPt = aSSLine->Value(aBindex-1); - //Not quadric point - Standard_Real aU0 = 0.0, aV0 = 0.0; - //Quadric point - Standard_Real aUQuadRef = 0.0, aVQuadRef = 0.0; + Standard_Real aCompareTol3D = Precision::Confusion(); + Standard_Real aCompareTol2D = Precision::PConfusion(); - if(IsReversed) + IntSurf_PntOn2S aNewPoint = aRefPt; + IntPatch_SpecPntType aLastType = IntPatch_SPntNone; + + if(aPrePointExist == IntPatch_SPntSeamUV) { - aRefPt.Parameters(aU0, aV0, aUQuadRef, aVQuadRef); + aPrePointExist = IntPatch_SPntNone; + aLastType = IntPatch_SPntSeamUV; + IntPatch_SpecialPoints::AddCrossUVIsoPoint(theQSurf, thePSurf, + aRefPt, theTolTang, + aNewPoint, IsReversed); } - else - { - aRefPt.Parameters(aUQuadRef, aVQuadRef, aU0, aV0); - } - - if(aPrePointExist == PrePoint_SEAMUV) - { - aPrePointExist = PrePoint_NONE; - - gp_Pnt aPQuad; - Standard_Real aUquad = 0.0; - Standard_Real aVquad = 0.0; - - theQSurf->D0(aUquad, aVquad, aPQuad); - - Extrema_GenLocateExtPS anExtr(thePSurf->Surface()); - anExtr.Perform(aPQuad, aU0, aV0); - - if(!anExtr.IsDone()) - { - break; - } - - if(anExtr.SquareDistance() < theTolTang*theTolTang) - { - anExtr.Point().Parameter(aU0, aV0); - gp_Pnt aP0(anExtr.Point().Value()); - - IntSurf_PntOn2S aNewPoint; - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), IsReversed, aU0, aV0); - - if(!aNewPoint.IsSame(aRefPt, Precision::Confusion())) - { - //Adjust found U-paramter to previous point of the Walking-line - Standard_Real aDeltaPar = aUQuadRef-aUquad; - const Standard_Real anIncrU = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aUquad += anIncrU; - aDeltaPar = aUQuadRef-aUquad; - } - - //Adjust found V-paramter to previous point of the Walking-line - aDeltaPar = aVQuadRef-aVquad; - const Standard_Real anIncrV = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aVquad += anIncrV; - aDeltaPar = aVQuadRef-aVquad; - } - - aNewPoint.SetValue(!IsReversed, aUquad, aVquad); - - sline->Add(aNewPoint); - aPrePointExist = PrePoint_SEAMUV; - PrePoint = aNewPoint; - } - } - } - else if(aPrePointExist == PrePoint_SEAMV) + else if(aPrePointExist == IntPatch_SPntSeamV) {//WLine goes through seam - aPrePointExist = PrePoint_NONE; + aPrePointExist = IntPatch_SPntNone; + aLastType = IntPatch_SPntSeamV; + + //Not quadric point + Standard_Real aU0 = 0.0, aV0 = 0.0; + //Quadric point + Standard_Real aUQuadRef = 0.0, aVQuadRef = 0.0; + + if(IsReversed) + { + aRefPt.Parameters(aU0, aV0, aUQuadRef, aVQuadRef); + } + else + { + aRefPt.Parameters(aUQuadRef, aVQuadRef, aU0, aV0); + } - FuncPreciseSeam aF(theQSurf, thePSurf, Standard_False); math_Vector aTol(1, 3), aStartPoint(1,3), - anInfBound(1, 3), aSupBound(1, 3); - + anInfBound(1, 3), aSupBound(1, 3); + //Parameters on parametric surface Standard_Real aUp = 0.0, aVp = 0.0; if(IsReversed) @@ -2858,358 +2607,51 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin aSupBound(2) = thePSurf->LastVParameter(); aSupBound(3) = theQSurf->LastUParameter(); - math_FunctionSetRoot aSRF(aF, aTol); - aSRF.Perform(aF, aStartPoint, anInfBound, aSupBound); - - if(!aSRF.IsDone()) - { - break; - } - - // Now aStartPoint is useless. Therefore, we use it for keeping - // new point. - aSRF.Root(aStartPoint); - - //On parametric - aU0 = aStartPoint(1); - aV0 = aStartPoint(2); - - //On quadric - Standard_Real aUquad = aStartPoint(3); - Standard_Real aVquad = 0.0; - const gp_Pnt aPQuad(theQSurf->Value(aUquad, aVquad)); - const gp_Pnt aP0(thePSurf->Value(aU0, aV0)); - - { - //Adjust found U-paramter to previous point of the Walking-line - Standard_Real aDeltaPar = aVQuadRef-aVquad; - const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aVquad += anIncr; - aDeltaPar = aVQuadRef-aVquad; - } - } - - IntSurf_PntOn2S aNewPoint; - if(IsReversed) - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); - else - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); - - if(!aNewPoint.IsSame(aRefPt, Precision::Confusion(), Precision::PConfusion())) - { - aNewPoint.SetValue(!IsReversed, aUquad, aVquad); - sline->Add(aNewPoint); - aPrePointExist = PrePoint_SEAMV; - PrePoint = aNewPoint; - } - else - { - if(sline->NbPoints() == 1) - { - //FIRST point of the sline is the pole of the quadric. - //Therefore, there is no point in decomposition. - - PrePoint = aRefPt; - aPrePointExist = PrePoint_SEAMV; - } - } + IntPatch_SpecialPoints:: + AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_False, + aTol, aStartPoint, anInfBound, aSupBound, + aNewPoint, IsReversed); } - else if(aPrePointExist == PrePoint_POLESEAMU) - {//Check if WLine goes through pole - - aPrePointExist = PrePoint_NONE; + else if(aPrePointExist == IntPatch_SPntPoleSeamU) + { + aPrePointExist = IntPatch_SPntNone; - //aPQuad is Pole - gp_Pnt aPQuad; - Standard_Real aUquad = 0.0; - Standard_Real aVquad = 0.0; - - if(theQuad.TypeQuadric() == GeomAbs_Sphere) + IntPatch_Point aVert; + aVert.SetValue(aRefPt); + + if(IntPatch_SpecialPoints:: + AddSingularPole(theQSurf, thePSurf, aRefPt, theTolTang, + aVert, aNewPoint, IsReversed)) { - aVquad = Sign(M_PI_2, aVQuadRef); - } - else if(theQuad.TypeQuadric() == GeomAbs_Cone) - { - const Standard_Real aRadius = theQuad.Cone().RefRadius(); - const Standard_Real aSemiAngle = theQuad.Cone().SemiAngle(); - aVquad = -aRadius/sin(aSemiAngle); - } - else - { - Standard_TypeMismatch::Raise( "IntPatch_ImpPrmIntersection.cxx," - " DecomposeResult(...): " - "Unsupported quadric with Pole"); - } - - theQSurf->D0(aUquad, aVquad, aPQuad); - - Extrema_GenLocateExtPS anExtr(thePSurf->Surface()); - anExtr.Perform(aPQuad, aU0, aV0); - - if(!anExtr.IsDone()) - { - break; - } - - if(anExtr.SquareDistance() < theTolTang*theTolTang) - { //Pole is an intersection point - //(lies in the quadric and the parametric surface) - - anExtr.Point().Parameter(aU0, aV0); - gp_Pnt aP0(anExtr.Point().Value()); - - IntSurf_PntOn2S aNewPoint; - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), IsReversed, aU0, aV0); - - if(!aNewPoint.IsSame(aRefPt, Precision::Confusion())) - { - //Found pole does not exist in the Walking-line - //It must be added there (with correct 2D-parameters) - - //2D-parameters of theparametric surface have already been found (aU0, aV0). - //Let find 2D-parameters on the quadric. - - //The algorithm depends on the type of the quadric. Here we consider a Sphere only. - //Analogical result can be made for another types (e.g. cone, but formulas will - //be different) in case of need. - - //First of all, we need in adjusting thePSurf in the coordinate system of the Sphere - //(in order to make the equation of the sphere maximal simple). However, as it will be - //shown later, thePSurf is used in algorithm in order to get its derivatives. Therefore, - //for improving performance, transformation of these vectors is enough (there is no point - //in transformation of full surface). - - gp_Pnt aPtemp; - gp_Vec aVecDu, aVecDv; - thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv); - - //Transforms parametric surface in coordinate-system of the quadric - gp_Trsf aTr; - aTr.SetTransformation((theQuad.TypeQuadric() == GeomAbs_Sphere) ? - theQuad.Sphere().Position() : - theQuad.Cone().Position()); - - //Derivatives of transformed thePSurf - aVecDu.Transform(aTr); - aVecDv.Transform(aTr); - - if(theQuad.TypeQuadric() == GeomAbs_Sphere) - { - //The intersection point (including the pole) - //must be satisfied to the following system: - - // \left\{\begin{matrix} - // R*\cos (U_{q})*\cos (V_{q})=S_{x}(U_{s},V_{s}) - // R*\sin (U_{q})*\cos (V_{q})=S_{y}(U_{s},V_{s}) - // R*\sin (V_{q})=S_{z}(U_{s},V_{s}) - // \end{matrix}\right, - //where - // R is the radius of the sphere; - // @S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf; - // @U_{s}@ and @V_{s}@ are equal to aU0 and aV0 corespondingly; - // @U_{q}@ and @V_{q}@ are equal to aUquad and aVquad corespondingly. - - //Consequently (from first two equations), - // \left\{\begin{matrix} - // \cos (U_{q}) = \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})} - // \sin (U_{q}) = \frac{S_{y}(U_{s},V_{s})}{R*\cos (V_{q})} - // \end{matrix}\right. - - //For pole, - // V_{q}=\pm \pi /2 \Rightarrow \cos (V_{q}) = 0 (denominator is equal to 0). - - //Therefore, computation U_{q} directly is impossibly. - // - //Let @V_{q}@ tends to @\pm \pi /2@. - //Then (indeterminate form is evaluated in accordance of L'Hospital rule), - // \cos (U_{q}) = \lim_{V_{q} \to (\pi /2-0)} - // \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}= - // -\lim_{V_{q} \to (\pi /2-0)} - // \frac{\frac{\partial S_{x}} - // {\partial U_{s}}*\frac{\mathrm{d} U_{s}} - // {\mathrm{d} V_{q}}+\frac{\partial S_{x}} - // {\partial V_{s}}*\frac{\mathrm{d} V_{s}} - // {\mathrm{d} V_{q}}}{R*\sin (V_{q})} = - // -\frac{1}{R}*\frac{\mathrm{d} U_{s}} - // {\mathrm{d} V_{q}}*(\frac{\partial S_{x}} - // {\partial U_{s}}+\frac{\partial S_{x}} - // {\partial V_{s}}*\frac{\mathrm{d} V_{s}} - // {\mathrm{d} U_{s}}) = - // -\frac{1}{R}*\frac{\mathrm{d} V_{s}} - // {\mathrm{d} V_{q}}*(\frac{\partial S_{x}} - // {\partial U_{s}}*\frac{\mathrm{d} U_{s}} - // {\mathrm{d} V_{s}}+\frac{\partial S_{x}} - // {\partial V_{s}}). - - //Analogicaly for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@). - - //Let mean, that - // \cos (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \cos (U_{q}) \left | _{V_{q} \to (\pi /2-0)} - // \sin (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \sin (U_{q}) \left | _{V_{q} \to (\pi /2-0)} - - //From the 3rd equation of the system, we obtain - // \frac{\mathrm{d} (R*\sin (V_{q}))}{\mathrm{d} V_{q}} = - // \frac{\mathrm{d} S_{z}(U_{s},V_{s})}{\mathrm{d} V_{q}} - //or - // R*\cos (V_{q}) = \frac{\partial S_{z}}{\partial U_{s}}* - // \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}} - // {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}}. - - //If @V_{q}=\pm \pi /2@, then - // \frac{\partial S_{z}}{\partial U_{s}}* - // \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}} - // {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}} = 0. - - //Consequently, if @\frac{\partial S_{z}}{\partial U_{s}} \neq 0 @ then - // \frac{\mathrm{d} U_{s}}{\mathrm{d} V_{s}} = - // -\frac{\frac{\partial S_{z}}{\partial V_{s}}} - // {\frac{\partial S_{z}}{\partial U_{s}}}. - - //If @ \frac{\partial S_{z}}{\partial V_{s}} \neq 0 @ then - // \frac{\mathrm{d} V_{s}}{\mathrm{d} U_{s}} = - // -\frac{\frac{\partial S_{z}}{\partial U_{s}}} - // {\frac{\partial S_{z}}{\partial V_{s}}} - - //Cases, when @ \frac{\partial S_{z}}{\partial U_{s}} = - //\frac{\partial S_{z}}{\partial V_{s}} = 0 @ are not consider here. - //The reason is written below. - - //Vector with {@ \cos (U_{q}) @, @ \sin (U_{q}) @} coordinates. - //Ask to pay attention to the fact that this vector is always normalyzed. - gp_Vec2d aV1; - - if( (Abs(aVecDu.Z()) < Precision::PConfusion()) && - (Abs(aVecDv.Z()) < Precision::PConfusion())) - { - //Example of this exception is intersection a plane with a sphere - //when the plane tangents the sphere in some pole (i.e. only one - //intersection point, not line). In this case, U-coordinate of the - //sphere is undefined (can be realy anything). - //Another reason is that we have tangent zone around the pole - //(see bug #26576). - //Computation correct value of aUquad is impossible. Therefore, - //we should throw an exception in this case. - //Also, any Walking line cannot be created in this case. - //Hovewer, Restriction line is not created by intersection algorithm. - //It is already exists (above we check simply, if this line is - //intersection line). - //Therefore, we can try to find the aUquad-parameter on (existing) - //Restriction line. Here, we will do it with - //extrapolation algorithm. - //Use interpolation algorithm is wrong because aUquad parameter - //jumps while the line going though the pole. - - if((theLine->ArcType() == IntPatch_Walking) || - (aBindex < 3)) - { - //We must have at least two previous points - //in order to do linear extrapolation. - Standard_NumericError:: - Raise("IntPatch_ImpPrmIntersection.cxx, DecomposeResult(...): " - "Cannot find UV-coordinate for quadric in the pole"); - } - else - { -#ifdef INTPATCH_IMPPRMINTERSECTION_DEBUG - cout << "Cannot find UV-coordinate for quadric in the pole." - " See considered comment above. IntPatch_ImpPrmIntersection.cxx," - " DecomposeResult(...)" << endl; -#endif - - // *----------*------------x - // QuadPrev QuadRef Quad (must be found) - - const IntSurf_PntOn2S& aPt2S = aSSLine->Value(aBindex-2); - //Quadric point - Standard_Real aUQuadPrev = 0.0, aVQuadPrev = 0.0; - if(IsReversed) - { - aPt2S.ParametersOnS2(aUQuadPrev, aVQuadPrev); - } - else - { - aPt2S.ParametersOnS1(aUQuadPrev, aVQuadPrev); - } - - Standard_NumericError_Raise_if( - Abs(aVQuadPrev - aVQuadRef) < gp::Resolution(), - "Division by zero"); - - aUquad = - aUQuadPrev + (aUQuadRef - aUQuadPrev)* - (aVquad - aVQuadPrev)/(aVQuadRef - aVQuadPrev); - } - } - else - { - if(Abs(aVecDu.Z()) > Abs(aVecDv.Z())) - { - const Standard_Real aDusDvs = aVecDv.Z()/aVecDu.Z(); - - aV1.SetCoord( aVecDu.X()*aDusDvs - aVecDv.X(), - aVecDu.Y()*aDusDvs - aVecDv.Y()); - } - else - { - const Standard_Real aDvsDus = aVecDu.Z()/aVecDv.Z(); - aV1.SetCoord( aVecDv.X()*aDvsDus - aVecDu.X(), - aVecDv.Y()*aDvsDus - aVecDu.Y()); - } - - aV1.Normalize(); - - if(Abs(aV1.X()) > Abs(aV1.Y())) - aUquad = Sign(asin(aV1.Y()), aVquad); - else - aUquad = Sign(acos(aV1.X()), aVquad); - } - - { - //Adjust found U-paramter to previous point of the Walking-line - Standard_Real aDeltaPar = aUQuadRef-aUquad; - const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aUquad += anIncr; - aDeltaPar = aUQuadRef-aUquad; - } - } - } - - aNewPoint.SetValue(!IsReversed, aUquad, aVquad); - - sline->Add(aNewPoint); - aPrePointExist = PrePoint_POLE; - PrePoint = aNewPoint; - } // if(!aNewPoint.IsSame(aRefPt, Precision::Confusion())) - else - { - aPrePointExist = PrePoint_NONE; - - if(sline->NbPoints() == 1) - { - //FIRST point of the sline is the pole of the quadric. - //Therefore, there is no point in decomposition. - - PrePoint = aRefPt; - aPrePointExist = PrePoint_POLE; - } - } - } //if(anExtr.SquareDistance() < aTol*aTol) + aPrePointExist = IntPatch_SPntPole; + aLastType = IntPatch_SPntPole; + aCompareTol2D = -1.0; + } //if(IntPatch_AddSpecialPoints::AddSingularPole(...)) else {//Pole is not an intersection point - aPrePointExist = PrePoint_SEAMU; + aPrePointExist = IntPatch_SPntSeamU; } } - if(aPrePointExist == PrePoint_SEAMU) + if(aPrePointExist == IntPatch_SPntSeamU) {//WLine goes through seam + aPrePointExist = IntPatch_SPntNone; + aLastType = IntPatch_SPntSeamU; - aPrePointExist = PrePoint_NONE; + //Not quadric point + Standard_Real aU0 = 0.0, aV0 = 0.0; + //Quadric point + Standard_Real aUQuadRef = 0.0, aVQuadRef = 0.0; + + if(IsReversed) + { + aRefPt.Parameters(aU0, aV0, aUQuadRef, aVQuadRef); + } + else + { + aRefPt.Parameters(aUQuadRef, aVQuadRef, aU0, aV0); + } - FuncPreciseSeam aF(theQSurf, thePSurf, Standard_True); math_Vector aTol(1, 3), aStartPoint(1,3), anInfBound(1, 3), aSupBound(1, 3); @@ -3237,62 +2679,27 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin aSupBound(2) = thePSurf->LastVParameter(); aSupBound(3) = theQSurf->LastVParameter(); - math_FunctionSetRoot aSRF(aF, aTol); - aSRF.Perform(aF, aStartPoint, anInfBound, aSupBound); + IntPatch_SpecialPoints:: + AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_True, aTol, + aStartPoint, anInfBound, aSupBound, aNewPoint, + IsReversed); + } - if(!aSRF.IsDone()) + if(!aNewPoint.IsSame(aRefPt, aCompareTol3D, aCompareTol2D)) + { + sline->Add(aNewPoint); + aPrePointExist = aLastType; + PrePoint = aNewPoint; + } + else + { + if(sline->NbPoints() == 1) { - break; - } + //FIRST point of the sline is the pole of the quadric. + //Therefore, there is no point in decomposition. - // Now aStartPoint is useless. Therefore, we use it for keeping - // new point. - aSRF.Root(aStartPoint); - - //On parametric - aU0 = aStartPoint(1); - aV0 = aStartPoint(2); - - //On quadric - Standard_Real aUquad = 0.0; - Standard_Real aVquad = aStartPoint(3); - const gp_Pnt aPQuad(theQSurf->Value(aUquad, aVquad)); - const gp_Pnt aP0(thePSurf->Value(aU0, aV0)); - - { - //Adjust found U-paramter to previous point of the Walking-line - Standard_Real aDeltaPar = aUQuadRef-aUquad; - const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); - while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) - { - aUquad += anIncr; - aDeltaPar = aUQuadRef-aUquad; - } - } - - IntSurf_PntOn2S aNewPoint; - if(IsReversed) - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); - else - aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); - - if(!aNewPoint.IsSame(aRefPt, Precision::Confusion(), Precision::PConfusion())) - { - aNewPoint.SetValue(!IsReversed, aUquad, aVquad); - sline->Add(aNewPoint); - aPrePointExist = PrePoint_SEAMU; - PrePoint = aNewPoint; - } - else - { - if(sline->NbPoints() == 1) - { - //FIRST point of the sline is the pole of the quadric. - //Therefore, there is no point in decomposition. - - PrePoint = aRefPt; - aPrePointExist = PrePoint_SEAMU; - } + PrePoint = aRefPt; + aPrePointExist = aLastType; } } diff --git a/src/IntPatch/IntPatch_Intersection.cxx b/src/IntPatch/IntPatch_Intersection.cxx index 754e89af44..0a441abe5b 100644 --- a/src/IntPatch/IntPatch_Intersection.cxx +++ b/src/IntPatch/IntPatch_Intersection.cxx @@ -12,6 +12,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include #include #include @@ -21,22 +22,9 @@ #include #include #include -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include -#include - -#include -#define DEBUG 0 -static const Standard_Integer aNbPointsInALine = 200; //====================================================================== // function: SequenceOfLine @@ -1332,165 +1320,105 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the { IntPatch_ImpImpIntersection interii(theS1,theD1,theS2,theD2, myTolArc,myTolTang, theIsReqToKeepRLine); - if (interii.IsDone()) + + if (!interii.IsDone()) { - done = (interii.GetStatus() == IntPatch_ImpImpIntersection::IntStatus_OK); - empt = interii.IsEmpty(); - if (!empt) - { - tgte = interii.TangentFaces(); - if (tgte) - oppo = interii.OppositeFaces(); - - Standard_Boolean isQuadSet = Standard_False; - IntSurf_Quadric Quad1,Quad2; - - for (Standard_Integer i = 1; i <= interii.NbLines(); i++) - { - const Handle(IntPatch_Line)& line = interii.Line(i); - if (line->ArcType() == IntPatch_Analytic) - { - if(!isQuadSet) - { - isQuadSet = Standard_True; - - const GeomAbs_SurfaceType aTyps1 = theS1->GetType(); - const GeomAbs_SurfaceType aTyps2 = theS2->GetType(); - - switch(aTyps1) - { - case GeomAbs_Plane: - Quad1.SetValue(theS1->Plane()); - break; - - case GeomAbs_Cylinder: - Quad1.SetValue(theS1->Cylinder()); - break; - - case GeomAbs_Sphere: - Quad1.SetValue(theS1->Sphere()); - break; - - case GeomAbs_Cone: - Quad1.SetValue(theS1->Cone()); - break; - - case GeomAbs_Torus: - Quad1.SetValue(theS1->Torus()); - break; - - default: - isQuadSet = Standard_False; - break; - } - - switch(aTyps2) - { - case GeomAbs_Plane: - Quad2.SetValue(theS2->Plane()); - break; - case GeomAbs_Cylinder: - Quad2.SetValue(theS2->Cylinder()); - break; - - case GeomAbs_Sphere: - Quad2.SetValue(theS2->Sphere()); - break; - - case GeomAbs_Cone: - Quad2.SetValue(theS2->Cone()); - break; - - case GeomAbs_Torus: - Quad2.SetValue(theS2->Torus()); - break; - - default: - isQuadSet = Standard_False; - break; - } - - if(!isQuadSet) - { - break; - } - } - - IntPatch_ALineToWLine AToW(Quad1,Quad2,0.01,0.05,aNbPointsInALine); - Handle(IntPatch_WLine) wlin = - AToW.MakeWLine(Handle(IntPatch_ALine)::DownCast(line)); - wlin->EnablePurging(Standard_False); - slin.Append(wlin); - } - else - { - if(line->ArcType() == IntPatch_Walking) - { - Handle(IntPatch_WLine)::DownCast(line)->EnablePurging(Standard_False); - } - - slin.Append(line); - } - } - - for (Standard_Integer i = 1; i <= interii.NbPnts(); i++) - { - spnt.Append(interii.Point(i)); - } - - if((theTyps1 == GeomAbs_Cylinder) && (theTyps2 == GeomAbs_Cylinder)) - { - IntPatch_WLineTool::JoinWLines( slin, spnt, TolTang, - theS1->IsUPeriodic()? theS1->UPeriod() : 0.0, - theS2->IsUPeriodic()? theS2->UPeriod() : 0.0, - theS1->IsVPeriodic()? theS1->VPeriod() : 0.0, - theS2->IsVPeriodic()? theS2->VPeriod() : 0.0, - theS1->FirstUParameter(), - theS1->LastUParameter(), - theS1->FirstVParameter(), - theS1->LastVParameter(), - theS2->FirstUParameter(), - theS2->LastUParameter(), - theS2->FirstVParameter(), - theS2->LastVParameter()); - } - - if(isQuadSet) - { - Bnd_Box2d aBx1, aBx2; - const Standard_Real aU1F = theS1->FirstUParameter(), - aU1L = theS1->LastUParameter(), - aV1F = theS1->FirstVParameter(), - aV1L = theS1->LastVParameter(), - aU2F = theS2->FirstUParameter(), - aU2L = theS2->LastUParameter(), - aV2F = theS2->FirstVParameter(), - aV2L = theS2->LastVParameter(); - aBx1.Add(gp_Pnt2d(aU1F, aV1F)); - aBx1.Add(gp_Pnt2d(aU1L, aV1F)); - aBx1.Add(gp_Pnt2d(aU1L, aV1L)); - aBx1.Add(gp_Pnt2d(aU1F, aV1L)); - aBx2.Add(gp_Pnt2d(aU2F, aV2F)); - aBx2.Add(gp_Pnt2d(aU2L, aV2F)); - aBx2.Add(gp_Pnt2d(aU2L, aV2L)); - aBx2.Add(gp_Pnt2d(aU2F, aV2L)); - - aBx1.Enlarge(Precision::PConfusion()); - aBx2.Enlarge(Precision::PConfusion()); - - IntPatch_WLineTool:: - ExtendTwoWlinesToEachOther(slin, Quad1, Quad2, TolTang, - theS1->IsUPeriodic()? theS1->UPeriod() : 0.0, - theS2->IsUPeriodic()? theS2->UPeriod() : 0.0, - theS1->IsVPeriodic()? theS1->VPeriod() : 0.0, - theS2->IsVPeriodic()? theS2->VPeriod() : 0.0, - aBx1, aBx2); - } - } - } - else + done = Standard_False; ParamParamPerfom(theS1, theD1, theS2, theD2, TolArc, TolTang, ListOfPnts, RestrictLine, theTyps1, theTyps2); + return; + } + + done = (interii.GetStatus() == IntPatch_ImpImpIntersection::IntStatus_OK); + empt = interii.IsEmpty(); + + if(empt) + { + return; + } + + const Standard_Integer aNbPointsInALine = 200; + + tgte = interii.TangentFaces(); + if (tgte) + oppo = interii.OppositeFaces(); + + Standard_Boolean isWLExist = Standard_False; + IntPatch_ALineToWLine AToW(theS1, theS2, aNbPointsInALine); + + for (Standard_Integer i = 1; i <= interii.NbLines(); i++) + { + const Handle(IntPatch_Line)& line = interii.Line(i); + if (line->ArcType() == IntPatch_Analytic) + { + isWLExist = Standard_True; + AToW.MakeWLine(Handle(IntPatch_ALine)::DownCast(line), slin); + } + else + { + if (line->ArcType() == IntPatch_Walking) + { + Handle(IntPatch_WLine)::DownCast(line)->EnablePurging(Standard_False); + } + + if((line->ArcType() != IntPatch_Restriction) || theIsReqToKeepRLine) + slin.Append(line); + } + } + + for (Standard_Integer i = 1; i <= interii.NbPnts(); i++) + { + spnt.Append(interii.Point(i)); + } + + if((theTyps1 == GeomAbs_Cylinder) && (theTyps2 == GeomAbs_Cylinder)) + { + IntPatch_WLineTool::JoinWLines( slin, spnt, TolTang, + theS1->IsUPeriodic()? theS1->UPeriod() : 0.0, + theS2->IsUPeriodic()? theS2->UPeriod() : 0.0, + theS1->IsVPeriodic()? theS1->VPeriod() : 0.0, + theS2->IsVPeriodic()? theS2->VPeriod() : 0.0, + theS1->FirstUParameter(), + theS1->LastUParameter(), + theS1->FirstVParameter(), + theS1->LastVParameter(), + theS2->FirstUParameter(), + theS2->LastUParameter(), + theS2->FirstVParameter(), + theS2->LastVParameter()); + } + + if(isWLExist) + { + Bnd_Box2d aBx1, aBx2; + const Standard_Real aU1F = theS1->FirstUParameter(), + aU1L = theS1->LastUParameter(), + aV1F = theS1->FirstVParameter(), + aV1L = theS1->LastVParameter(), + aU2F = theS2->FirstUParameter(), + aU2L = theS2->LastUParameter(), + aV2F = theS2->FirstVParameter(), + aV2L = theS2->LastVParameter(); + aBx1.Add(gp_Pnt2d(aU1F, aV1F)); + aBx1.Add(gp_Pnt2d(aU1L, aV1F)); + aBx1.Add(gp_Pnt2d(aU1L, aV1L)); + aBx1.Add(gp_Pnt2d(aU1F, aV1L)); + aBx2.Add(gp_Pnt2d(aU2F, aV2F)); + aBx2.Add(gp_Pnt2d(aU2L, aV2F)); + aBx2.Add(gp_Pnt2d(aU2L, aV2L)); + aBx2.Add(gp_Pnt2d(aU2F, aV2L)); + + aBx1.Enlarge(Precision::PConfusion()); + aBx2.Enlarge(Precision::PConfusion()); + + const Standard_Real + anArrOfPeriod[4] = {theS1->IsUPeriodic()? theS1->UPeriod() : 0.0, + theS1->IsVPeriodic()? theS1->VPeriod() : 0.0, + theS2->IsUPeriodic()? theS2->UPeriod() : 0.0, + theS2->IsVPeriodic()? theS2->VPeriod() : 0.0}; + IntPatch_WLineTool::ExtendTwoWLines(slin, theS1, theS2, TolTang, + anArrOfPeriod, aBx1, aBx2); + } } //======================================================================= diff --git a/src/IntPatch/IntPatch_Point.hxx b/src/IntPatch/IntPatch_Point.hxx index 5c9367b765..414e464f38 100644 --- a/src/IntPatch/IntPatch_Point.hxx +++ b/src/IntPatch/IntPatch_Point.hxx @@ -54,6 +54,10 @@ public: Standard_EXPORT void SetValue (const gp_Pnt& Pt, const Standard_Real Tol, const Standard_Boolean Tangent); void SetValue (const gp_Pnt& Pt); + + //! Sets the value of member + void SetValue (const IntSurf_PntOn2S& thePOn2S); + void SetTolerance (const Standard_Real Tol); diff --git a/src/IntPatch/IntPatch_Point.lxx b/src/IntPatch/IntPatch_Point.lxx index c2b409b618..7bd5fb444a 100644 --- a/src/IntPatch/IntPatch_Point.lxx +++ b/src/IntPatch/IntPatch_Point.lxx @@ -27,6 +27,14 @@ inline void IntPatch_Point::SetValue (const gp_Pnt& Pt) pt.SetValue(Pt); } +//======================================================================= +////function : SetValue +//purpose : +//======================================================================= +inline void IntPatch_Point::SetValue(const IntSurf_PntOn2S& thePOn2S) +{ + pt = thePOn2S; +} inline void IntPatch_Point::SetTolerance (const Standard_Real Tol) { diff --git a/src/IntPatch/IntPatch_PointLine.cxx b/src/IntPatch/IntPatch_PointLine.cxx index 5109061cc8..3598b108bf 100644 --- a/src/IntPatch/IntPatch_PointLine.cxx +++ b/src/IntPatch/IntPatch_PointLine.cxx @@ -14,12 +14,11 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #include + +#include #include -#include -#include -#include +#include IMPLEMENT_STANDARD_RTTIEXT(IntPatch_PointLine,IntPatch_Line) @@ -39,4 +38,165 @@ IntPatch_PointLine::IntPatch_PointLine (const Standard_Boolean Tang) : IntPatch_Line(Tang) {} +//======================================================================= +//function : CurvatureRadiusOfIntersLine +//purpose : +// ATTENTION!!! +// Returns negative value if computation is not possible +//======================================================================= +Standard_Real IntPatch_PointLine:: + CurvatureRadiusOfIntersLine(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const IntSurf_PntOn2S& theUVPoint) +{ + const Standard_Real aSmallValue = 1.0/Precision::Infinite(); + const Standard_Real aSqSmallValue = aSmallValue*aSmallValue; + Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0; + theUVPoint.Parameters(aU1, aV1, aU2, aV2); + gp_Pnt aPt; + gp_Vec aDU1, aDV1, aDUU1, aDUV1, aDVV1; + gp_Vec aDU2, aDV2, aDUU2, aDUV2, aDVV2; + + theS1->D2(aU1, aV1, aPt, aDU1, aDV1, aDUU1, aDVV1, aDUV1); + theS2->D2(aU2, aV2, aPt, aDU2, aDV2, aDUU2, aDVV2, aDUV2); + +#if 0 + //The code in this block contains TEST CASES for + //this algorithm only. It is stupedly to create OCCT-test for + //the method, which will be changed possibly never. + //However, if we do something in this method we can check its + //functionality easily. For that: + // 1. Initialyze aTestID variable by the correct value; + // 2. Compile this test code fragment. + + int aTestID = 0; + Standard_Real anExpectedSqRad = -1.0; + switch(aTestID) + { + case 1: + //Intersection between two spherical surfaces: O1(0.0, 0.0, 0.0), R1 = 3 + //and O2(5.0, 0.0, 0.0), R2 = 5.0. + //Considered point has coordinates: (0.9, 0.0, 0.3*sqrt(91.0)). + + aDU1.SetCoord(0.00000000000000000, 0.90000000000000002, 0.00000000000000000); + aDV1.SetCoord(-2.8618176042508372, 0.00000000000000000, 0.90000000000000002); + aDUU1.SetCoord(-0.90000000000000002, 0.00000000000000000, 0.00000000000000000); + aDUV1.SetCoord(0.00000000000000000, -2.8618176042508372, 0.00000000000000000); + aDVV1.SetCoord(-0.90000000000000002, 0.00000000000000000, -2.8618176042508372); + aDU2.SetCoord(0.00000000000000000, -4.0999999999999996, 0.00000000000000000); + aDV2.SetCoord(-2.8618176042508372, 0.00000000000000000, -4.0999999999999996); + aDUU2.SetCoord(4.0999999999999996, 0.00000000000000000, 0.00000000000000000); + aDUV2.SetCoord(0.00000000000000000, -2.8618176042508372, 0.00000000000000000); + aDVV2.SetCoord(4.0999999999999996, 0.00000000000000000, -2.8618176042508372); + anExpectedSqRad = 819.0/100.0; + break; + case 2: + //Intersection between spherical surfaces: O1(0.0, 0.0, 0.0), R1 = 10 + //and the plane 3*x+4*y+z=26. + //Considered point has coordinates: (-1.68, 5.76, 8.0). + + aDU1.SetCoord(-5.76, -1.68, 0.0); + aDV1.SetCoord(2.24, -7.68, 6.0); + aDUU1.SetCoord(1.68, -5.76, 0.0); + aDUV1.SetCoord(7.68, 2.24, 0.0); + aDVV1.SetCoord(1.68, -5.76, -8.0); + aDU2.SetCoord(1.0, 0.0, -3.0); + aDV2.SetCoord(0.0, 1.0, -4.0); + aDUU2.SetCoord(0.0, 0.0, 0.0); + aDUV2.SetCoord(0.0, 0.0, 0.0); + aDVV2.SetCoord(0.0, 0.0, 0.0); + anExpectedSqRad = 74.0; + break; + default: + aTestID = 0; + break; + } +#endif + + const gp_Vec aN1(aDU1.Crossed(aDV1)), aN2(aDU2.Crossed(aDV2)); + //Tangent vactor to the intersection curve + const gp_Vec aCTan(aN1.Crossed(aN2)); + const Standard_Real aSqMagnFDer = aCTan.SquareMagnitude(); + + if(aSqMagnFDer < aSqSmallValue) + return -1.0; + + Standard_Real aDuS1 = 0.0, aDvS1 = 0.0, aDuS2 = 0.0, aDvS2 = 1.0; + + { + //This algorithm is described in NonSingularProcessing() function + //in ApproxInt_ImpPrmSvSurfaces.gxx file + Standard_Real aSqNMagn = aN1.SquareMagnitude(); + gp_Vec aTgU(aCTan.Crossed(aDU1)), aTgV(aCTan.Crossed(aDV1)); + Standard_Real aDeltaU = aTgV.SquareMagnitude()/aSqNMagn; + Standard_Real aDeltaV = aTgU.SquareMagnitude()/aSqNMagn; + + aDuS1 = Sign(sqrt(aDeltaU), aTgV.Dot(aN1)); + aDvS1 = -Sign(sqrt(aDeltaV), aTgU.Dot(aN1)); + + aSqNMagn = aN2.SquareMagnitude(); + aTgU.SetXYZ(aCTan.Crossed(aDU2).XYZ()); + aTgV.SetXYZ(aCTan.Crossed(aDV2).XYZ()); + aDeltaU = aTgV.SquareMagnitude()/aSqNMagn; + aDeltaV = aTgU.SquareMagnitude()/aSqNMagn; + + aDuS2 = Sign(sqrt(aDeltaU), aTgV.Dot(aN2)); + aDvS2 = -Sign(sqrt(aDeltaV), aTgU.Dot(aN2)); + } + + //According to "Marching along surface/surface intersection curves + //with an adaptive step length" + //by Tz.E.Stoyagov + //(http://www.sciencedirect.com/science/article/pii/016783969290046R) + //we obtain the system: + // {A*a+B*b=F1 + // {B*a+C*b=F2 + //where a and b should be found. + //After that, 2nd derivative of the intersection curve can be computed as + // r''(t)=a*aN1+b*aN2. + + const Standard_Real aA = aN1.Dot(aN1), aB = aN1.Dot(aN2), aC = aN2.Dot(aN2); + const Standard_Real aDetSyst = aB*aB - aA*aC; + + if(Abs(aDetSyst) < aSmallValue) + {//Indetermined system solution + return -1.0; + } + + const Standard_Real aF1 = aDuS1*aDuS1*aDUU1.Dot(aN1) + + 2.0*aDuS1*aDvS1*aDUV1.Dot(aN1) + + aDvS1*aDvS1*aDVV1.Dot(aN1); + const Standard_Real aF2 = aDuS2*aDuS2*aDUU2.Dot(aN2) + + 2.0*aDuS2*aDvS2*aDUV2.Dot(aN2) + + aDvS2*aDvS2*aDVV2.Dot(aN2); + + //Principal normal to the intersection curve + const gp_Vec aCNorm((aF1*aC-aF2*aB)/aDetSyst*aN1 + (aA*aF2-aF1*aB)/aDetSyst*aN2); + const Standard_Real aSqMagnSDer = aCNorm.CrossSquareMagnitude(aCTan); + + if(aSqMagnSDer < aSqSmallValue) + {//Intersection curve has null curvature in observed point + return Precision::Infinite(); + } + + //square of curvature radius + const Standard_Real aFactSqRad = aSqMagnFDer*aSqMagnFDer*aSqMagnFDer/aSqMagnSDer; + +#if 0 + if(aTestID) + { + if(Abs(aFactSqRad - anExpectedSqRad) < Precision::Confusion()) + { + printf("OK: Curvature radius is equal to expected (%5.10g)", anExpectedSqRad); + } + else + { + printf("Error: Curvature radius is not equal to expected: %5.10g != %5.10g", + aFactSqRad, anExpectedSqRad); + } + } +#endif + + return sqrt(aFactSqRad); +} diff --git a/src/IntPatch/IntPatch_PointLine.hxx b/src/IntPatch/IntPatch_PointLine.hxx index 9dc3bad2fb..ec0a78a869 100644 --- a/src/IntPatch/IntPatch_PointLine.hxx +++ b/src/IntPatch/IntPatch_PointLine.hxx @@ -17,22 +17,14 @@ #ifndef _IntPatch_PointLine_HeaderFile #define _IntPatch_PointLine_HeaderFile -#include +#include #include -#include -#include -#include -#include -#include -#include -class Standard_DomainError; -class Standard_OutOfRange; class IntSurf_PntOn2S; class IntSurf_LineOn2S; +class IntPatch_Point; +class Adaptor3d_HSurface; - -class IntPatch_PointLine; DEFINE_STANDARD_HANDLE(IntPatch_PointLine, IntPatch_Line) //! Definition of an intersection line between two @@ -42,7 +34,6 @@ DEFINE_STANDARD_HANDLE(IntPatch_PointLine, IntPatch_Line) //! defined in the class WLine or RLine (Restriction line). class IntPatch_PointLine : public IntPatch_Line { - public: //! Adds a vertex in the list. If theIsPrepend == TRUE the new @@ -76,6 +67,15 @@ public: //! Returns set of intersection points Standard_EXPORT virtual Handle(IntSurf_LineOn2S) Curve() const = 0; + //! Returns the radius of curvature of + //! the intersection line in given point. + //! Returns negative value if computation is not possible. + Standard_EXPORT static Standard_Real + CurvatureRadiusOfIntersLine(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const IntSurf_PntOn2S& theUVPoint); + + DEFINE_STANDARD_RTTIEXT(IntPatch_PointLine,IntPatch_Line) protected: diff --git a/src/IntPatch/IntPatch_SpecPntType.hxx b/src/IntPatch/IntPatch_SpecPntType.hxx new file mode 100644 index 0000000000..40ccced431 --- /dev/null +++ b/src/IntPatch/IntPatch_SpecPntType.hxx @@ -0,0 +1,34 @@ +//! Created on: 2016-06-03 +//! Created by: NIKOLAI BUKHALOV +//! Copyright (c) 2016 OPEN CASCADE SAS +//! +//! This file is part of Open CASCADE Technology software library. +//! +//! This library is free software; you can redistribute it and/or modify it under +//! the terms of the GNU Lesser General Public License version 2.1 as published +//! by the Free Software Foundation, with special exception defined in the file +//! OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +//! distribution for complete text of the license and disclaimer of any warranty. +//! +//! Alternatively, this file may be used under the terms of Open CASCADE +//! commercial license or contractual agreement. + +#ifndef _IntPatch_SpecPntType_HeaderFile +#define _IntPatch_SpecPntType_HeaderFile + +//! This enum describe the different kinds of +//! special (singular) points of Surface-Surface +//! intersection algorithm. Such as pole of sphere, +//! apex of cone, point on U- or V-seam etc. + +enum IntPatch_SpecPntType +{ + IntPatch_SPntNone, + IntPatch_SPntSeamU, + IntPatch_SPntSeamV, + IntPatch_SPntSeamUV, + IntPatch_SPntPoleSeamU, + IntPatch_SPntPole +}; + +#endif // _IntPatch_SpecPntType_HeaderFile \ No newline at end of file diff --git a/src/IntPatch/IntPatch_SpecialPoints.cxx b/src/IntPatch/IntPatch_SpecialPoints.cxx new file mode 100644 index 0000000000..81d4130977 --- /dev/null +++ b/src/IntPatch/IntPatch_SpecialPoints.cxx @@ -0,0 +1,717 @@ +//! Created on: 2016-06-03 +//! Created by: NIKOLAI BUKHALOV +//! Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The function for searching intersection point, which +// lies in the seam-edge of the quadric definetely. +class FuncPreciseSeam: public math_FunctionSetWithDerivatives +{ +public: + FuncPreciseSeam(const Handle(Adaptor3d_HSurface)& theQSurf, // quadric + const Handle(Adaptor3d_HSurface)& thePSurf, // another surface + const Standard_Boolean isTheUSeam): + myQSurf(theQSurf), + myPSurf(thePSurf), + mySeamCoordInd(isTheUSeam? 1 : 0) // Defines, U- or V-seam is used + { + }; + + virtual Standard_Integer NbVariables() const + { + return 3; + }; + + virtual Standard_Integer NbEquations() const + { + return 3; + } + + virtual Standard_Boolean Value(const math_Vector& theX, + math_Vector& theF) + { + try + { + const Standard_Integer anIndX = theX.Lower(), anIndF = theF.Lower(); + Standard_Real aUV[] = {0.0, 0.0}; + aUV[mySeamCoordInd] = theX(anIndX+2); + const gp_Pnt aP1(myPSurf->Value(theX(anIndX), theX(anIndX+1))); + const gp_Pnt aP2(myQSurf->Value(aUV[0], aUV[1])); + + (aP1.XYZ()-aP2.XYZ()).Coord(theF(anIndF), theF(anIndF+1), theF(anIndF+2)); + } + catch(Standard_Failure) + { + return Standard_False; + } + + return Standard_True; + }; + + virtual Standard_Boolean Derivatives(const math_Vector& theX, + math_Matrix& theD) + { + try + { + const Standard_Integer anIndX = theX.Lower(), + anIndRD = theD.LowerRow(), + anIndCD = theD.LowerCol(); + Standard_Real aUV[] = {0.0, 0.0}; + aUV[mySeamCoordInd] = theX(anIndX+2); + + gp_Pnt aPt; + + //0 for U-coordinate, 1 - for V one + gp_Vec aD1[2], aD2[2]; + myPSurf->D1(theX(anIndX), theX(anIndX+1), aPt, aD1[0], aD1[1]); + myQSurf->D1(aUV[0], aUV[1], aPt, aD2[0], aD2[1]); + + // d/dX1 + aD1[0].Coord(theD(anIndRD, anIndCD), + theD(anIndRD+1, anIndCD), theD(anIndRD+2, anIndCD)); + + // d/dX2 + aD1[1].Coord(theD(anIndRD, anIndCD+1), + theD(anIndRD+1, anIndCD+1), theD(anIndRD+2, anIndCD+1)); + + // d/dX3 + aD2[mySeamCoordInd].Reversed().Coord(theD(anIndRD, anIndCD+2), + theD(anIndRD+1, anIndCD+2), theD(anIndRD+2, anIndCD+2)); + } + catch(Standard_Failure) + { + return Standard_False; + } + + return Standard_True; + }; + + virtual Standard_Boolean Values (const math_Vector& theX, + math_Vector& theF, + math_Matrix& theD) + { + if(!Value(theX, theF)) + return Standard_False; + + if(!Derivatives(theX, theD)) + return Standard_False; + + return Standard_True; + } + +protected: + FuncPreciseSeam operator=(FuncPreciseSeam&); + +private: + const Handle(Adaptor3d_HSurface)& myQSurf; + const Handle(Adaptor3d_HSurface)& myPSurf; + + // 1 for U-coordinate, 0 - for V one. + const Standard_Integer mySeamCoordInd; +}; + +//======================================================================= +//function : IsPointOnSurface +//purpose : Checks if thePt is in theSurf (with given tolerance). +// Returns the foot of projection (theProjPt) and its parameters +// on theSurf. +//======================================================================= +static Standard_Boolean IsPointOnSurface(const Handle(Adaptor3d_HSurface)& theSurf, + const gp_Pnt& thePt, + const Standard_Real theTol, + gp_Pnt& theProjPt, + Standard_Real& theUpar, + Standard_Real& theVpar) +{ + Standard_Boolean aRetVal = Standard_False; + + switch(theSurf->GetType()) + { + case GeomAbs_Plane: + case GeomAbs_Cylinder: + case GeomAbs_Cone: + case GeomAbs_Sphere: + case GeomAbs_Torus: + case GeomAbs_SurfaceOfExtrusion: + case GeomAbs_SurfaceOfRevolution: + { + Extrema_ExtPS anExtr(thePt, theSurf->Surface(), theSurf->UResolution(theTol), + theSurf->VResolution(theTol), Extrema_ExtFlag_MIN); + if(!anExtr.IsDone() || (anExtr.NbExt() < 1)) + { + aRetVal = Standard_False; + } + else + { + Standard_Integer anExtrIndex = 1; + Standard_Real aSqDistMin = anExtr.SquareDistance(anExtrIndex); + for(Standard_Integer i = anExtrIndex + 1; i <= anExtr.NbExt(); i++) + { + const Standard_Real aSqD = anExtr.SquareDistance(i); + if(aSqD < aSqDistMin) + { + aSqDistMin = aSqD; + anExtrIndex = i; + } + } + + if(aSqDistMin > theTol*theTol) + { + aRetVal = Standard_False; + } + else + { + theProjPt.SetXYZ(anExtr.Point(anExtrIndex).Value().XYZ()); + anExtr.Point(anExtrIndex).Parameter(theUpar, theVpar); + aRetVal = Standard_True; + } + } + } + break; + default: + { + Extrema_GenLocateExtPS anExtr(theSurf->Surface()); + anExtr.Perform(thePt, theUpar, theVpar); + if(!anExtr.IsDone() || (anExtr.SquareDistance() > theTol*theTol)) + { + aRetVal = Standard_False; + } + else + { + anExtr.Point().Parameter(theUpar, theVpar); + theProjPt.SetXYZ(anExtr.Point().Value().XYZ()); + aRetVal = Standard_True; + } + } + break; + } + + return aRetVal; +} + +//======================================================================= +//function : AddCrossUVIsoPoint +//purpose : theQSurf is the surface possibly containing special point, +// thePSurf is another surface to intersect. +//======================================================================= +Standard_Boolean IntPatch_SpecialPoints:: + AddCrossUVIsoPoint(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const Standard_Real theTol, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed) +{ + Standard_Real anArrOfPeriod[4] = {0.0, 0.0, 0.0, 0.0}; + IntSurf::SetPeriod(theIsReversed ? thePSurf : theQSurf, + theIsReversed ? theQSurf : thePSurf, anArrOfPeriod); + + gp_Pnt aPQuad; + + //Not quadric point + Standard_Real aU0 = 0.0, aV0 = 0.0; + if(theIsReversed) + theRefPt.ParametersOnS1(aU0, aV0); + else + theRefPt.ParametersOnS2(aU0, aV0); + + //Quadric point + Standard_Real aUquad = 0.0, aVquad = 0.0; + + theQSurf->D0(aUquad, aVquad, aPQuad); + + Extrema_GenLocateExtPS anExtr(thePSurf->Surface()); + anExtr.Perform(aPQuad, aU0, aV0); + + if(!anExtr.IsDone()) + { + return Standard_False; + } + + if(anExtr.SquareDistance() > theTol*theTol) + { + return Standard_False; + } + + anExtr.Point().Parameter(aU0, aV0); + gp_Pnt aP0(anExtr.Point().Value()); + + if(theIsReversed) + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); + else + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); + + AdjustPointAndVertex(theRefPt, anArrOfPeriod, theAddedPoint); + + return Standard_True; +} + +//======================================================================= +//function : AddPointOnUorVIso +//purpose : theQSurf is the surface possibly containing special point, +// thePSurf is another surface to intersect. +//======================================================================= +Standard_Boolean IntPatch_SpecialPoints:: + AddPointOnUorVIso(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const Standard_Boolean theIsU, + const math_Vector& theToler, + const math_Vector& theInitPoint, + const math_Vector& theInfBound, + const math_Vector& theSupBound, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed) +{ + Standard_Real anArrOfPeriod[4] = {0.0, 0.0, 0.0, 0.0}; + IntSurf::SetPeriod(theIsReversed ? thePSurf : theQSurf, + theIsReversed ? theQSurf : thePSurf, anArrOfPeriod); + + FuncPreciseSeam aF(theQSurf, thePSurf, theIsU); + + math_FunctionSetRoot aSRF(aF, theToler); + aSRF.Perform(aF, theInitPoint, theInfBound, theSupBound); + + if(!aSRF.IsDone()) + { + return Standard_False; + } + + math_Vector aRoots(theInitPoint.Lower(), theInitPoint.Upper()); + aSRF.Root(aRoots); + + //On parametric + Standard_Real aU0 = aRoots(1), aV0 = aRoots(2); + + //On quadric + Standard_Real aUquad = theIsU ? 0.0 : aRoots(3); + Standard_Real aVquad = theIsU ? aRoots(3) : 0.0; + const gp_Pnt aPQuad(theQSurf->Value(aUquad, aVquad)); + const gp_Pnt aP0(thePSurf->Value(aU0, aV0)); + + if(theIsReversed) + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); + else + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); + + AdjustPointAndVertex(theRefPt, anArrOfPeriod, theAddedPoint); + return Standard_True; +} + +//======================================================================= +//function : AddSingularPole +//purpose : theQSurf is the surface possibly containing special point, +// thePSurf is another surface to intersect. +// Returns TRUE, if the pole is an intersection point. +//======================================================================= +Standard_Boolean IntPatch_SpecialPoints:: + AddSingularPole(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& thePtIso, + const Standard_Real theTol, + IntPatch_Point& theVertex, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed, + const Standard_Boolean theIsReqRefCheck) +{ + const Standard_Real aUpPeriod = thePSurf->IsUPeriodic() ? thePSurf->UPeriod() : 0.0; + const Standard_Real aUqPeriod = theQSurf->IsUPeriodic() ? theQSurf->UPeriod() : 0.0; + const Standard_Real aVpPeriod = thePSurf->IsVPeriodic() ? thePSurf->VPeriod() : 0.0; + const Standard_Real aVqPeriod = theQSurf->IsVPeriodic() ? theQSurf->VPeriod() : 0.0; + + const Standard_Real anArrOfPeriod[4] = {theIsReversed? aUpPeriod : aUqPeriod, + theIsReversed? aVpPeriod : aVqPeriod, + theIsReversed? aUqPeriod : aUpPeriod, + theIsReversed? aVqPeriod : aVpPeriod}; + + //On parametric + Standard_Real aU0 = 0.0, aV0 = 0.0; + //aPQuad is Pole + gp_Pnt aPQuad, aP0; + Standard_Real aUquad = 0.0, aVquad = 0.0; + if(theIsReversed) + theVertex.Parameters(aU0, aV0, aUquad, aVquad); + else + theVertex.Parameters(aUquad, aVquad, aU0, aV0); + + aUquad = 0.0; + + if(theQSurf->GetType() == GeomAbs_Sphere) + { + aVquad = Sign(M_PI_2, aVquad); + } + else if(theQSurf->GetType() == GeomAbs_Cone) + { + const gp_Cone aCo = theQSurf->Cone(); + const Standard_Real aRadius = aCo.RefRadius(); + const Standard_Real aSemiAngle = aCo.SemiAngle(); + aVquad = -aRadius / sin(aSemiAngle); + } + else + { + Standard_TypeMismatch::Raise( "IntPatch_SpecialPoints::AddSingularPole()," + "Unsupported quadric with Pole"); + } + + theQSurf->D0(aUquad, aVquad, aPQuad); + + if (theIsReqRefCheck && (aPQuad.SquareDistance(theVertex.Value()) >= theTol*theTol)) + { + return Standard_False; + } + + if(!IsPointOnSurface(thePSurf, aPQuad, theTol, aP0, aU0, aV0)) + { + return Standard_False; + } + + //Pole is an intersection point + //(lies in the quadric and the parametric surface) + + if(theIsReversed) + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); + else + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); + + Standard_Boolean isSame = Standard_False; + + if (theAddedPoint.IsSame(theVertex.PntOn2S(), Precision::Confusion())) + { + isSame = Standard_True; + } + + //Found pole does not exist in the Walking-line + //It must be added there (with correct 2D-parameters) + + //2D-parameters of theparametric surface have already been found (aU0, aV0). + //Let find 2D-parameters on the quadric. + + //The algorithm depends on the type of the quadric. Here we consider a Sphere only. + //Analogical result can be made for another types (e.g. cone, but formulas will + //be different) in case of need. + + //First of all, we need in adjusting thePSurf in the coordinate system of the Sphere + //(in order to make the equation of the sphere maximal simple). However, as it will be + //shown later, thePSurf is used in algorithm in order to get its derivatives. + //Therefore, for improving performance, transformation of these vectors is enough + //(there is no point in transformation of full surface). + + gp_Pnt aPtemp; + gp_Vec aVecDu, aVecDv; + thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv); + + //Transforms parametric surface in coordinate-system of the quadric + gp_Trsf aTr; + aTr.SetTransformation((theQSurf->GetType() == GeomAbs_Sphere) ? + theQSurf->Sphere().Position() : + theQSurf->Cone().Position()); + + //Derivatives of transformed thePSurf + aVecDu.Transform(aTr); + aVecDv.Transform(aTr); + + Standard_Boolean isIsoChoosen = Standard_False; + + if(theQSurf->GetType() == GeomAbs_Sphere) + { + //The intersection point (including the pole) + //must be satisfied to the following system: + + // \left\{\begin{matrix} + // R*\cos (U_{q})*\cos (V_{q})=S_{x}(U_{s},V_{s}) + // R*\sin (U_{q})*\cos (V_{q})=S_{y}(U_{s},V_{s}) + // R*\sin (V_{q})=S_{z}(U_{s},V_{s}) + // \end{matrix}\right, + //where + // R is the radius of the sphere; + // @S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf; + // @U_{s}@ and @V_{s}@ are equal to aU0 and aV0 corespondingly; + // @U_{q}@ and @V_{q}@ are equal to aUquad and aVquad corespondingly. + + //Consequently (from first two equations), + // \left\{\begin{matrix} + // \cos (U_{q}) = \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})} + // \sin (U_{q}) = \frac{S_{y}(U_{s},V_{s})}{R*\cos (V_{q})} + // \end{matrix}\right. + + //For pole, + // V_{q}=\pm \pi /2 \Rightarrow \cos (V_{q}) = 0 (denominator is equal to 0). + + //Therefore, computation U_{q} directly is impossibly. + // + //Let @V_{q}@ tends to @\pm \pi /2@. + //Then (indeterminate form is evaluated in accordance of L'Hospital rule), + // \cos (U_{q}) = \lim_{V_{q} \to (\pi /2-0)} + // \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}= + // -\lim_{V_{q} \to (\pi /2-0)} + // \frac{\frac{\partial S_{x}} + // {\partial U_{s}}*\frac{\mathrm{d} U_{s}} + // {\mathrm{d} V_{q}}+\frac{\partial S_{x}} + // {\partial V_{s}}*\frac{\mathrm{d} V_{s}} + // {\mathrm{d} V_{q}}}{R*\sin (V_{q})} = + // -\frac{1}{R}*\frac{\mathrm{d} U_{s}} + // {\mathrm{d} V_{q}}*(\frac{\partial S_{x}} + // {\partial U_{s}}+\frac{\partial S_{x}} + // {\partial V_{s}}*\frac{\mathrm{d} V_{s}} + // {\mathrm{d} U_{s}}) = + // -\frac{1}{R}*\frac{\mathrm{d} V_{s}} + // {\mathrm{d} V_{q}}*(\frac{\partial S_{x}} + // {\partial U_{s}}*\frac{\mathrm{d} U_{s}} + // {\mathrm{d} V_{s}}+\frac{\partial S_{x}} + // {\partial V_{s}}). + + //Analogicaly for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@). + + //Let mean, that + // \cos (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \cos (U_{q}) \left | _{V_{q} \to (\pi /2-0)} + // \sin (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \sin (U_{q}) \left | _{V_{q} \to (\pi /2-0)} + + //From the 3rd equation of the system, we obtain + // \frac{\mathrm{d} (R*\sin (V_{q}))}{\mathrm{d} V_{q}} = + // \frac{\mathrm{d} S_{z}(U_{s},V_{s})}{\mathrm{d} V_{q}} + //or + // R*\cos (V_{q}) = \frac{\partial S_{z}}{\partial U_{s}}* + // \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}} + // {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}}. + + //If @V_{q}=\pm \pi /2@, then + // \frac{\partial S_{z}}{\partial U_{s}}* + // \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}} + // {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}} = 0. + + //Consequently, if @\frac{\partial S_{z}}{\partial U_{s}} \neq 0 @ then + // \frac{\mathrm{d} U_{s}}{\mathrm{d} V_{s}} = + // -\frac{\frac{\partial S_{z}}{\partial V_{s}}} + // {\frac{\partial S_{z}}{\partial U_{s}}}. + + //If @ \frac{\partial S_{z}}{\partial V_{s}} \neq 0 @ then + // \frac{\mathrm{d} V_{s}}{\mathrm{d} U_{s}} = + // -\frac{\frac{\partial S_{z}}{\partial U_{s}}} + // {\frac{\partial S_{z}}{\partial V_{s}}} + + //Cases, when @ \frac{\partial S_{z}}{\partial U_{s}} = + //\frac{\partial S_{z}}{\partial V_{s}} = 0 @ are not consider here. + //The reason is written below. + + //Vector with {@ \cos (U_{q}) @, @ \sin (U_{q}) @} coordinates. + //Ask to pay attention to the fact that this vector is always normalyzed. + gp_Vec2d aV1; + + if( (Abs(aVecDu.Z()) < Precision::PConfusion()) && + (Abs(aVecDv.Z()) < Precision::PConfusion())) + { + //Example of this case is an intersection of a plane with a sphere + //when the plane tangents the sphere in some pole (i.e. only one + //intersection point, not line). In this case, U-coordinate of the + //sphere is undefined (can be realy anything). + //Another reason is that we have tangent zone around the pole + //(see bug #26576). + //Computation of correct value of aUquad is impossible. + //Therefore, (in oreder to return something) we will consider + //the intersection line goes along some isoline in neighbourhood + //of the pole. + +#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG + cout << "Cannot find UV-coordinate for quadric in the pole." + " See considered comment above. IntPatch_AddSpecialPoints.cxx," + " AddSingularPole(...)" << endl; +#endif + Standard_Real aUIso = 0.0, aVIso = 0.0; + if(theIsReversed) + thePtIso.ParametersOnS2(aUIso, aVIso); + else + thePtIso.ParametersOnS1(aUIso, aVIso); + + aUquad = aUIso; + isIsoChoosen = Standard_True; + } + else + { + if(Abs(aVecDu.Z()) > Abs(aVecDv.Z())) + { + const Standard_Real aDusDvs = aVecDv.Z()/aVecDu.Z(); + aV1.SetCoord( aVecDu.X()*aDusDvs - aVecDv.X(), + aVecDu.Y()*aDusDvs - aVecDv.Y()); + } + else + { + const Standard_Real aDvsDus = aVecDu.Z()/aVecDv.Z(); + aV1.SetCoord( aVecDv.X()*aDvsDus - aVecDu.X(), + aVecDv.Y()*aDvsDus - aVecDu.Y()); + } + + aV1.Normalize(); + + if(Abs(aV1.X()) > Abs(aV1.Y())) + aUquad = Sign(asin(aV1.Y()), aVquad); + else + aUquad = Sign(acos(aV1.X()), aVquad); + } + } + else //if(theQSurf->GetType() == GeomAbs_Cone) + { + // This case is not processed. However, + // it can be done using the same algorithm + // as for sphere (formulas will be different). + return Standard_False; + } + + if(theIsReversed) + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aU0, aV0, aUquad, aVquad); + else + theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0); + + if (isSame) + { + theVertex.SetValue(theAddedPoint); + return Standard_True; + } + + if (!isIsoChoosen) + { + AdjustPointAndVertex(theVertex.PntOn2S(), anArrOfPeriod, theAddedPoint); + } + else + { + theVertex.SetValue(theAddedPoint); + } + + return Standard_True; +} + +//======================================================================= +//function : ContinueAfterSpecialPoint +//purpose : +//======================================================================= +Standard_Boolean IntPatch_SpecialPoints:: + ContinueAfterSpecialPoint(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const IntPatch_SpecPntType theSPType, + const Standard_Real theTol2D, + IntSurf_PntOn2S& theNewPoint, + const Standard_Boolean theIsReversed) +{ + if(theSPType == IntPatch_SPntNone) + return Standard_False; + + //If the last point of the line is the pole of the quadric. + //In this case, Walking-line has been broken in this point. + //However, new line must start from this point. Here we must + //find its 2D-coordinates. + + //For sphere and cone, some intersection point is satisfied to the system + // \cos(U_{q}) = S_{x}(U_{s},V_{s})/F(V_{q}) + // \sin(U_{q}) = S_{y}(U_{s},V_{s})/F(V_{q}) + + //where + // @S_{x}@, @S_{y}@ are X and Y-coordinates of thePSurf; + // @U_{s}@ and @V_{s}@ are UV-parameters on thePSurf; + // @U_{q}@ and @V_{q}@ are UV-parameters on theQSurf; + // @F(V_{q}) @ is some function, which value independs on @U_{q}@ + // (form of this function depends on the type of the quadric). + + //When we go through the pole/apex, the function @F(V_{q}) @ changes sign. + //Therefore, some cases are possible, when only @\cos(U_{q}) @ or + //only @ \sin(U_{q}) @ change sign. + + //Consequently, when the line goes throug the pole, @U_{q}@ can be + //changed on @\pi /2 @ (but not less). + + if(theNewPoint.IsSame(theRefPt, Precision::Confusion(), theTol2D)) + { + return Standard_False; + } + + //Here, in case of pole/apex adding, we forbid "jumping" between two neighbor + //Walking-point with step greater than pi/4 + const Standard_Real aPeriod = (theSPType == IntPatch_SPntPole)? M_PI_2 : 2.0*M_PI; + + const Standard_Real aUpPeriod = thePSurf->IsUPeriodic() ? thePSurf->UPeriod() : 0.0; + const Standard_Real aUqPeriod = theQSurf->IsUPeriodic() ? aPeriod : 0.0; + const Standard_Real aVpPeriod = thePSurf->IsVPeriodic() ? thePSurf->VPeriod() : 0.0; + const Standard_Real aVqPeriod = theQSurf->IsVPeriodic() ? aPeriod : 0.0; + + const Standard_Real anArrOfPeriod[4] = {theIsReversed? aUpPeriod : aUqPeriod, + theIsReversed? aVpPeriod : aVqPeriod, + theIsReversed? aUqPeriod : aUpPeriod, + theIsReversed? aVqPeriod : aVpPeriod}; + + AdjustPointAndVertex(theRefPt, anArrOfPeriod, theNewPoint); + return Standard_True; +} + +//======================================================================= +//function : AdjustPointAndVertex +//purpose : +//======================================================================= +void IntPatch_SpecialPoints:: + AdjustPointAndVertex(const IntSurf_PntOn2S &theRefPoint, + const Standard_Real theArrPeriods[4], + IntSurf_PntOn2S &theNewPoint, + IntPatch_Point* const theVertex) +{ + Standard_Real aRefPar[2] = {0.0, 0.0}; + Standard_Real aPar[4] = {0.0, 0.0, 0.0, 0.0}; + theNewPoint.Parameters(aPar[0], aPar[1], aPar[2], aPar[3]); + + for(Standard_Integer i = 0; i < 4; i++) + { + if(theArrPeriods[i] == 0) + continue; + + const Standard_Real aPeriod = theArrPeriods[i], aHalfPeriod = 0.5*theArrPeriods[i]; + + if(i < 2) + {// 1st surface is used + theRefPoint.ParametersOnS1(aRefPar[0], aRefPar[1]); + } + else + { + theRefPoint.ParametersOnS2(aRefPar[0], aRefPar[1]); + } + + const Standard_Integer aRefInd = i%2; + + { + Standard_Real aDeltaPar = aRefPar[aRefInd]-aPar[i]; + const Standard_Real anIncr = Sign(aPeriod, aDeltaPar); + while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod)) + { + aPar[i] += anIncr; + aDeltaPar = aRefPar[aRefInd]-aPar[i]; + } + } + } + + if(theVertex) + (*theVertex).SetParameters(aPar[0], aPar[1], aPar[2], aPar[3]); + + theNewPoint.SetValue(aPar[0], aPar[1], aPar[2], aPar[3]); +} + diff --git a/src/IntPatch/IntPatch_SpecialPoints.hxx b/src/IntPatch/IntPatch_SpecialPoints.hxx new file mode 100644 index 0000000000..cfd2f74c29 --- /dev/null +++ b/src/IntPatch/IntPatch_SpecialPoints.hxx @@ -0,0 +1,125 @@ +//! Created on: 2016-06-03 +//! Created by: NIKOLAI BUKHALOV +//! Copyright (c) 2016 OPEN CASCADE SAS +//! +//! This file is part of Open CASCADE Technology software library. +//! +//! This library is free software; you can redistribute it and/or modify it under +//! the terms of the GNU Lesser General Public License version 2.1 as published +//! by the Free Software Foundation, with special exception defined in the file +//! OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +//! distribution for complete text of the license and disclaimer of any warranty. +//! +//! Alternatively, this file may be used under the terms of Open CASCADE +//! commercial license or contractual agreement. + +#ifndef _IntPatch_SpecialPoints_HeaderFile +#define _IntPatch_SpecialPoints_HeaderFile + +//! Contains methods to add some special points +//! (such as apex of cone, pole of sphere, +//! point on surface boundary etc.) in the intersection line. + +#include +#include + +class Adaptor3d_HSurface; +class IntPatch_Point; +class IntSurf_PntOn2S; +class math_Vector; + +class IntPatch_SpecialPoints +{ +public: + //! Adds the point defined as intersection + //! of two isolines (U = 0 and V = 0) on theQSurf in theLine. + //! theRefPt is used to correct adjusting parameters. + //! If theIsReversed is TRUE then theQSurf correspond to the + //! second (otherwise, the first) surface while forming + //! intersection point IntSurf_PntOn2S. + Standard_EXPORT static Standard_Boolean + AddCrossUVIsoPoint(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const Standard_Real theTol3d, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed + = Standard_False); + + //! Adds the point lain strictly in the isoline U = 0 or V = 0 of theQSurf, + //! in theLine. + //! theRefPt is used to correct adjusting parameters. + //! If theIsReversed is TRUE then theQSurf corresponds to the + //! second (otherwise, the first) surface while forming + //! intersection point IntSurf_PntOn2S. + Standard_EXPORT static Standard_Boolean + AddPointOnUorVIso(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const Standard_Boolean theIsU, + const math_Vector& theToler, + const math_Vector& theInitPoint, + const math_Vector& theInfBound, + const math_Vector& theSupBound, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed + = Standard_False); + + //! Computes the pole of sphere to add it in the intersection line. + //! Stores the result in theAddedPoint variable (does not add in the line). + //! At that, cone and sphere (with singularity) must be set in theQSurf parameter. + //! By default (if theIsReversed == FALSE), theQSurf is the first surface of the + //! Walking line. If it is not, theIsReversed parameter must be set to TRUE. + //! theIsReqRefCheck is TRUE if and only if 3D-point of theRefPt must be pole or apex + //! for check (e.g. if it is vertex). + //! thePtIso is the reference point for obtaining isoline where must be placed the Apex/Pole. + //! + //! ATTENTION!!! + //! theVertex must be initialized before calling the method . + Standard_EXPORT static Standard_Boolean + AddSingularPole(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& thePtIso, + const Standard_Real theTol3d, + IntPatch_Point& theVertex, + IntSurf_PntOn2S& theAddedPoint, + const Standard_Boolean theIsReversed = + Standard_False, + const Standard_Boolean theIsReqRefCheck = + Standard_False); + + //! Special point has already been added in the line. Now, we need in correct + //! prolongation of the line or in start new line. This function returns new point. + //! + //! ATTENTION!!! + //! theNewPoint is not only Output parameter. It is Input/Output one. I.e. + //! theNewPoint is reference point together with theRefPt. + Standard_EXPORT static Standard_Boolean + ContinueAfterSpecialPoint(const Handle(Adaptor3d_HSurface)& theQSurf, + const Handle(Adaptor3d_HSurface)& thePSurf, + const IntSurf_PntOn2S& theRefPt, + const IntPatch_SpecPntType theSPType, + const Standard_Real theTol2D, + IntSurf_PntOn2S& theNewPoint, + const Standard_Boolean theIsReversed + = Standard_False); + + //! Sets theNewPoint parameters in 2D-space the closest to + //! theRefPoint with help of adding/subtracting corresponding periods. + //! theArrPeriods must be filled as follows: + //! {, , + //! , }. + //! If theVertex != 0 then its parameters will befilled as + //! corresponding parameters of theNewPoint. + //! + //! ATTENTION!!! + //! theNewPoint is not only Output parameter. It is Input/Output one. I.e. + //! theNewPoint is reference point together with theRefPt. + Standard_EXPORT static void + AdjustPointAndVertex(const IntSurf_PntOn2S &theRefPoint, + const Standard_Real theArrPeriods[4], + IntSurf_PntOn2S &theNewPoint, + IntPatch_Point* const theVertex = 0); +}; + +#endif // _IntPatch_AddSpecialPoints_HeaderFile diff --git a/src/IntPatch/IntPatch_WLineTool.cxx b/src/IntPatch/IntPatch_WLineTool.cxx index bb09d22da2..0f30e2ad92 100644 --- a/src/IntPatch/IntPatch_WLineTool.cxx +++ b/src/IntPatch/IntPatch_WLineTool.cxx @@ -16,13 +16,15 @@ #include #include #include +#include +#include // It is pure empirical value. const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6; //Bit-mask is used for information about //the operation made in -//IntPatch_WLineTool::ExtendTwoWlinesToEachOther() method. +//IntPatch_WLineTool::ExtendTwoWLines(...) method. enum { IntPatchWT_EnAll = 0x00, @@ -32,6 +34,13 @@ enum IntPatchWT_DisFirstFirst = 0x08 }; +enum IntPatchWT_WLsConnectionType +{ + IntPatchWT_NotConnected, + IntPatchWT_Singular, + IntPatchWT_EachOther +}; + //======================================================================= //function : MinMax //purpose : Replaces theParMIN = MIN(theParMIN, theParMAX), @@ -667,27 +676,6 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf, return Standard_False; } -//======================================================================= -//function : AbjustPeriodicToPrevPoint -//purpose : Returns theCurrentParam in order to the distance betwen -// theRefParam and theCurrentParam is less than 0.5*thePeriod. -//======================================================================= -static void AbjustPeriodicToPrevPoint(const Standard_Real theRefParam, - const Standard_Real thePeriod, - Standard_Real& theCurrentParam) -{ - if(thePeriod == 0.0) - return; - - Standard_Real aDeltaPar = 2.0*(theRefParam - theCurrentParam); - const Standard_Real anIncr = Sign(thePeriod, aDeltaPar); - while(Abs(aDeltaPar) > thePeriod) - { - theCurrentParam += anIncr; - aDeltaPar = 2.0*(theRefParam-theCurrentParam); - } -} - //======================================================================= //function : IsIntersectionPoint //purpose : Returns True if thePmid is intersection point @@ -696,31 +684,73 @@ static void AbjustPeriodicToPrevPoint(const Standard_Real theRefParam, // will be recomputed and returned. //======================================================================= static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid, - const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, + const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, const IntSurf_PntOn2S& theRefPt, const Standard_Real theTol, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - Standard_Real &theU1, - Standard_Real &theV1, - Standard_Real &theU2, - Standard_Real &theV2) + const Standard_Real* const theArrPeriods, + IntSurf_PntOn2S& theNewPt) { - Standard_Real aU1Ref = 0.0, aV1Ref = 0.0, aU2Ref = 0.0, aV2Ref = 0.0; - theRefPt.Parameters(aU1Ref, aV1Ref, aU2Ref, aV2Ref); - theS1.Parameters(thePmid, theU1, theV1); - theS2.Parameters(thePmid, theU2, theV2); + Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0; + + switch(theS1->GetType()) + { + case GeomAbs_Plane: + ElSLib::Parameters(theS1->Plane(), thePmid, aU1, aV1); + break; - AbjustPeriodicToPrevPoint(aU1Ref, theU1Period, theU1); - AbjustPeriodicToPrevPoint(aV1Ref, theV1Period, theV1); - AbjustPeriodicToPrevPoint(aU2Ref, theU2Period, theU2); - AbjustPeriodicToPrevPoint(aV2Ref, theV2Period, theV2); + case GeomAbs_Cylinder: + ElSLib::Parameters(theS1->Cylinder(), thePmid, aU1, aV1); + break; - const gp_Pnt aP1(theS1.Value(theU1, theV1)); - const gp_Pnt aP2(theS2.Value(theU2, theV2)); + case GeomAbs_Sphere: + ElSLib::Parameters(theS1->Sphere(), thePmid, aU1, aV1); + break; + + case GeomAbs_Cone: + ElSLib::Parameters(theS1->Cone(), thePmid, aU1, aV1); + break; + + case GeomAbs_Torus: + ElSLib::Parameters(theS1->Torus(), thePmid, aU1, aV1); + break; + + default: + return Standard_False; + } + + switch(theS2->GetType()) + { + case GeomAbs_Plane: + ElSLib::Parameters(theS2->Plane(), thePmid, aU2, aV2); + break; + + case GeomAbs_Cylinder: + ElSLib::Parameters(theS2->Cylinder(), thePmid, aU2, aV2); + break; + + case GeomAbs_Sphere: + ElSLib::Parameters(theS2->Sphere(), thePmid, aU2, aV2); + break; + + case GeomAbs_Cone: + ElSLib::Parameters(theS2->Cone(), thePmid, aU2, aV2); + break; + + case GeomAbs_Torus: + ElSLib::Parameters(theS2->Torus(), thePmid, aU2, aV2); + break; + + default: + return Standard_False; + } + + theNewPt.SetValue(thePmid, aU1, aV1, aU2, aV2); + + IntPatch_SpecialPoints::AdjustPointAndVertex(theRefPt, theArrPeriods, theNewPt); + + const gp_Pnt aP1(theS1->Value(aU1, aV1)); + const gp_Pnt aP2(theS2->Value(aU2, aV2)); return (aP1.SquareDistance(aP2) <= theTol*theTol); } @@ -809,10 +839,7 @@ static void ExtendLast(const Handle(IntPatch_WLine)& theWline, static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1, const Bnd_Box2d& theBoxS2, const IntSurf_PntOn2S &thePOn2S, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period) + const Standard_Real* const theArrPeriods) { Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0; Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0; @@ -823,10 +850,10 @@ static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1, theBoxS1.Get(aU1min, aV1min, aU1max, aV1max); theBoxS2.Get(aU2min, aV2min, aU2max, aV2max); - aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theU1Period); - aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theV1Period); - aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theU2Period); - aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theV2Period); + aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theArrPeriods[0]); + aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theArrPeriods[1]); + aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theArrPeriods[2]); + aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theArrPeriods[3]); return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) || theBoxS2.IsOut(gp_Pnt2d(aU2, aV2))); @@ -835,84 +862,138 @@ static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1, //======================================================================= //function : CheckArgumentsToExtend //purpose : Check if extending is possible -// (see IntPatch_WLineTool::ExtendTwoWlinesToEachOther) +// (see IntPatch_WLineTool::ExtendTwoWLines) //======================================================================= -Standard_Boolean CheckArgumentsToExtend(const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, - const IntSurf_PntOn2S& thePtWL1, - const IntSurf_PntOn2S& thePtWL2, - IntSurf_PntOn2S& theNewPoint, - const gp_Vec& theVec1, - const gp_Vec& theVec2, - const gp_Vec& theVec3, - const Bnd_Box2d& theBoxS1, - const Bnd_Box2d& theBoxS2, - const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period) +static IntPatchWT_WLsConnectionType + CheckArgumentsToExtend(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const IntSurf_PntOn2S& thePtWL1, + const IntSurf_PntOn2S& thePtWL2, + IntSurf_PntOn2S& theNewPoint, + const gp_Vec& theVec1, + const gp_Vec& theVec2, + const gp_Vec& theVec3, + const Bnd_Box2d& theBoxS1, + const Bnd_Box2d& theBoxS2, + const Standard_Real theToler3D, + const Standard_Real* const theArrPeriods) { const Standard_Real aSqToler = theToler3D*theToler3D; if(theVec3.SquareMagnitude() <= aSqToler) { - return Standard_False; + return IntPatchWT_NotConnected; } if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) || (theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) || (theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle)) { - return Standard_False; + return IntPatchWT_NotConnected; } const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ())); - Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0; + Standard_Real aNewPar[4] = {0.0, 0.0, 0.0, 0.0}; - theBoxS1.Get(aU1, aV1, aU2, aV2); - const Standard_Real aU1f = aU1, aV1f = aV1; - theBoxS2.Get(aU1, aV1, aU2, aV2); - const Standard_Real aU2f = aU1, aV2f = aV1; + //Left-bottom corner + Standard_Real aParLBC[4] = {0.0, 0.0, 0.0, 0.0}; + theBoxS1.Get(aParLBC[0], aParLBC[1], aNewPar[0], aNewPar[0]); + theBoxS2.Get(aParLBC[2], aParLBC[3], aNewPar[0], aNewPar[0]); if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period, - aU1, aV1, aU2, aV2)) + theArrPeriods, theNewPoint)) { - return Standard_False; + return IntPatchWT_NotConnected; } - theNewPoint.SetValue(aPmid, aU1, aV1, aU2, aV2); - - if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, - theU1Period, theU2Period, - theV1Period, theV2Period)) + if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, theArrPeriods)) { - return Standard_False; + return IntPatchWT_NotConnected; } - Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0, - aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0; + Standard_Real aParWL1[4] = {0.0, 0.0, 0.0, 0.0}, + aParWL2[4] = {0.0, 0.0, 0.0, 0.0}; + + thePtWL1.Parameters(aParWL1[0], aParWL1[1], aParWL1[2], aParWL1[3]); + thePtWL2.Parameters(aParWL2[0], aParWL2[1], aParWL2[2], aParWL2[3]); + theNewPoint.Parameters(aNewPar[0], aNewPar[1], aNewPar[2], aNewPar[3]); - thePtWL1.Parameters(aU11, aV11, aU21, aV21); - thePtWL2.Parameters(aU12, aV12, aU22, aV22); - - if(IsOnPeriod(aU11 - aU1f, aU12 - aU1f, theU1Period) || - IsOnPeriod(aV11 - aV1f, aV12 - aV1f, theV1Period) || - IsOnPeriod(aU21 - aU2f, aU22 - aU2f, theU2Period) || - IsOnPeriod(aV21 - aV2f, aV22 - aV2f, theV2Period)) + Standard_Boolean isOnBoundary = Standard_False; + for(Standard_Integer i = 0; i < 4; i++) { - return Standard_False; + if(IsOnPeriod(aParWL1[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[i])) + { + //Check, if we intersect surface boundary when we will extend Wline1 or Wline2 + //to theNewPoint + MinMax(aParWL1[i], aParWL2[i]); + if(theArrPeriods[i] > 0.0) + { + if(aNewPar[i] > aParWL2[i]) + { + //Source situation: + // + //---*---------------*------------*----- + // aParWL1[i] aParWL2[i] aNewPar[i] + // + //After possible adjusting: + // + //---*---------------*------------*----- + // aParWL1[i] aNewPar[i] aParWL2[i] + // + //Now we will be able to extend every WLine to + //aNewPar[i] to make them close to each other. + //However, it is necessary to add check if we + //intersect boundary. + const Standard_Real aPar = aParWL1[i] + + theArrPeriods[0]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[0]); + aParWL1[i] = aParWL2[i]; + aParWL2[i] = aPar; + } + else if(aNewPar[i] < aParWL1[i]) + { + //See comments to main "if". + //Source situation: + // + //---*---------------*------------*----- + // aNewPar[i] aParWL1[i] aParWL2[i] + // + //After possible adjusting: + // + //---*---------------*------------*----- + // aParWL1[i] aNewPar[i] aParWL2[i] + + const Standard_Real aPar = aParWL2[i] - + theArrPeriods[0]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[0]); + aParWL2[i] = aParWL1[i]; + aParWL1[i] = aPar; + } + } + + if( IsOnPeriod(aParWL1[i] - aParLBC[i], aNewPar[i] - aParLBC[i], theArrPeriods[0]) || + IsOnPeriod(aNewPar[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[0])) + { + return IntPatchWT_NotConnected; + } + else + { + isOnBoundary = Standard_True; + } + } } - return Standard_True; + if(isOnBoundary) + { + return IntPatchWT_Singular; + } + + return IntPatchWT_EachOther; } //======================================================================= //function : CheckArgumentsToJoin //purpose : Check if joining is possible -// (see IntPatch_WLineTool::JoinWLines) +// (see IntPatch_WLineTool::JoinWLines(...)) //======================================================================= Standard_Boolean CheckArgumentsToJoin(const gp_Vec& theVec1, const gp_Vec& theVec2) @@ -928,40 +1009,40 @@ Standard_Boolean CheckArgumentsToJoin(const gp_Vec& theVec1, //purpose : Performs extending theWLine1 and theWLine2 through their // respecting start point. //======================================================================= -static void ExtendTwoWLFirstFirst(const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, - const Handle(IntPatch_WLine)& theWLine1, - const Handle(IntPatch_WLine)& theWLine2, - const IntSurf_PntOn2S& thePtWL1, - const IntSurf_PntOn2S& thePtWL2, - const gp_Vec& theVec1, - const gp_Vec& theVec2, - const gp_Vec& theVec3, - const Bnd_Box2d& theBoxS1, - const Bnd_Box2d& theBoxS2, - const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - unsigned int &theCheckResult, - Standard_Boolean &theHasBeenJoined) +static void ExtendTwoWLFirstFirst(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const Handle(IntPatch_WLine)& theWLine1, + const Handle(IntPatch_WLine)& theWLine2, + const IntSurf_PntOn2S& thePtWL1, + const IntSurf_PntOn2S& thePtWL2, + const gp_Vec& theVec1, + const gp_Vec& theVec2, + const gp_Vec& theVec3, + const Bnd_Box2d& theBoxS1, + const Bnd_Box2d& theBoxS2, + const Standard_Real theToler3D, + const Standard_Real* const theArrPeriods, + unsigned int &theCheckResult, + Standard_Boolean &theHasBeenJoined) { IntSurf_PntOn2S aPOn2S; - if(!CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, - theVec1, theVec2, theVec3, - theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period)) - { + const IntPatchWT_WLsConnectionType aCheckRes = + CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, + theVec1, theVec2, theVec3, + theBoxS1, theBoxS2, + theToler3D, theArrPeriods); + + if(aCheckRes != IntPatchWT_NotConnected) + theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst); + else return; - } - - theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst); + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S); ExtendFirst(theWLine1, aPOn2S); + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S); ExtendFirst(theWLine2, aPOn2S); - if(theHasBeenJoined) + if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular)) return; Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine(); @@ -1002,8 +1083,8 @@ static void ExtendTwoWLFirstFirst(const IntSurf_Quadric& theS1, //purpose : Performs extending theWLine1 through its start point and theWLine2 // through its end point. //======================================================================= -static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, +static void ExtendTwoWLFirstLast(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, const Handle(IntPatch_WLine)& theWLine1, const Handle(IntPatch_WLine)& theWLine2, const IntSurf_PntOn2S& thePtWL1, @@ -1014,28 +1095,28 @@ static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1, const Bnd_Box2d& theBoxS1, const Bnd_Box2d& theBoxS2, const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, + const Standard_Real* const theArrPeriods, unsigned int &theCheckResult, Standard_Boolean &theHasBeenJoined) { IntSurf_PntOn2S aPOn2S; - if(!CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, - theVec1, theVec2, theVec3, - theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period)) - { + const IntPatchWT_WLsConnectionType aCheckRes = + CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, + theVec1, theVec2, theVec3, + theBoxS1, theBoxS2, + theToler3D, theArrPeriods); + + if(aCheckRes != IntPatchWT_NotConnected) + theCheckResult |= IntPatchWT_DisLastLast; + else return; - } - - theCheckResult |= IntPatchWT_DisLastLast; + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S); ExtendFirst(theWLine1, aPOn2S); + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S); ExtendLast (theWLine2, aPOn2S); - if(theHasBeenJoined) + if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular)) return; Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine(); @@ -1074,8 +1155,8 @@ static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1, //purpose : Performs extending theWLine1 through its end point and theWLine2 // through its start point. //======================================================================= -static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, +static void ExtendTwoWLLastFirst(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, const Handle(IntPatch_WLine)& theWLine1, const Handle(IntPatch_WLine)& theWLine2, const IntSurf_PntOn2S& thePtWL1, @@ -1086,28 +1167,28 @@ static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1, const Bnd_Box2d& theBoxS1, const Bnd_Box2d& theBoxS2, const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, + const Standard_Real* const theArrPeriods, unsigned int &theCheckResult, Standard_Boolean &theHasBeenJoined) { IntSurf_PntOn2S aPOn2S; - if(!CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, - theVec1, theVec2, theVec3, - theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period)) - { + const IntPatchWT_WLsConnectionType aCheckRes = + CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, + theVec1, theVec2, theVec3, + theBoxS1, theBoxS2, + theToler3D, theArrPeriods); + + if(aCheckRes != IntPatchWT_NotConnected) + theCheckResult |= IntPatchWT_DisLastLast; + else return; - } - - theCheckResult |= IntPatchWT_DisLastLast; + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S); ExtendLast (theWLine1, aPOn2S); + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S); ExtendFirst(theWLine2, aPOn2S); - if(theHasBeenJoined) + if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular)) { return; } @@ -1142,8 +1223,8 @@ static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1, //function : ExtendTwoWLLastLast //purpose : //======================================================================= -static void ExtendTwoWLLastLast(const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, +static void ExtendTwoWLLastLast(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, const Handle(IntPatch_WLine)& theWLine1, const Handle(IntPatch_WLine)& theWLine2, const IntSurf_PntOn2S& thePtWL1, @@ -1154,28 +1235,28 @@ static void ExtendTwoWLLastLast(const IntSurf_Quadric& theS1, const Bnd_Box2d& theBoxS1, const Bnd_Box2d& theBoxS2, const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - unsigned int &/*theCheckResult*/, + const Standard_Real* const theArrPeriods, + unsigned int &theCheckResult, Standard_Boolean &theHasBeenJoined) { IntSurf_PntOn2S aPOn2S; - if(!CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, - theVec1, theVec2, theVec3, - theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period)) - { - return; - } + const IntPatchWT_WLsConnectionType aCheckRes = + CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S, + theVec1, theVec2, theVec3, + theBoxS1, theBoxS2, + theToler3D, theArrPeriods); - //theCheckResult |= IntPatchWT_DisLastLast; + if(aCheckRes != IntPatchWT_NotConnected) + theCheckResult |= IntPatchWT_DisLastLast; + else + return; + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S); ExtendLast(theWLine1, aPOn2S); + IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S); ExtendLast(theWLine2, aPOn2S); - if(theHasBeenJoined) + if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular)) return; Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine(); @@ -1403,6 +1484,7 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin, { const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2); const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2); + Standard_Boolean aCond = CheckArgumentsToJoin(gp_Vec(aPntFWL1.Value(), aPt1.Value()), gp_Vec(aPt2.Value(), aPntFWL2.Value())); @@ -1549,20 +1631,17 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin, } //======================================================================= -//function : ExtendTwoWlinesToEachOther +//function : ExtendTwoWLines //purpose : Performs extending theWLine1 and theWLine2 through their // respecting end point. //======================================================================= -void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin, - const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, - const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - const Bnd_Box2d& theBoxS1, - const Bnd_Box2d& theBoxS2) +void IntPatch_WLineTool::ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin, + const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Real theToler3D, + const Standard_Real* const theArrPeriods, + const Bnd_Box2d& theBoxS1, + const Bnd_Box2d& theBoxS2) { if(theSlin.Length() < 2) return; @@ -1587,6 +1666,49 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts()) continue; + const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1); + const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2); + + const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1); + const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1); + + //Enable/Disable of some ckeck. Bit-mask is used for it. + //E.g. if 1st point of aWLine1 matches with + //1st point of aWLine2 then we do not need in check + //1st point of aWLine1 and last point of aWLine2 etc. + unsigned int aCheckResult = IntPatchWT_EnAll; + + //If aWLine1 is already connected with another Wline then + //there is no point in extending. + for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; + aNumOfLine2 <= theSlin.Length(); aNumOfLine2++) + { + Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine):: + DownCast(theSlin.Value(aNumOfLine2))); + + if(aWLine2.IsNull()) + continue; + + const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1); + const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aWLine2->NbPnts()); + + if( aPntFWL1.IsSame(aPntFWL2, theToler3D) || + aPntFWL1.IsSame(aPntLWL2, theToler3D) ) + { + aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast; + } + + if( aPntLWL1.IsSame(aPntFWL2, theToler3D) || + aPntLWL1.IsSame(aPntFWL2, theToler3D)) + { + aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast; + } + } + + if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast | + IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast)) + continue; + for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++) { @@ -1602,22 +1724,10 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts()) continue; - //Enable/Disable of some ckeck. Bit-mask is used for it. - //E.g. if 1st point of aWLine1 matches with - //1st point of aWLine2 then we do not need in check - //1st point of aWLine1 and last point of aWLine2 etc. - unsigned int aCheckResult = IntPatchWT_EnAll; - Standard_Boolean hasBeenJoined = Standard_False; const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts(); - const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1); - const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2); - - const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1); - const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1); - const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1); const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2); @@ -1632,8 +1742,7 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2, aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period, - aCheckResult, hasBeenJoined); + theArrPeriods, aCheckResult, hasBeenJoined); } if(!(aCheckResult & IntPatchWT_DisFirstLast)) @@ -1644,8 +1753,7 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2, aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period, - aCheckResult, hasBeenJoined); + theArrPeriods, aCheckResult, hasBeenJoined); } if(!(aCheckResult & IntPatchWT_DisLastFirst)) @@ -1656,8 +1764,7 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2, aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period, - aCheckResult, hasBeenJoined); + theArrPeriods, aCheckResult, hasBeenJoined); } if(!(aCheckResult & IntPatchWT_DisLastLast)) @@ -1668,8 +1775,7 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2, aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D, - theU1Period, theU2Period, theV1Period, theV2Period, - aCheckResult, hasBeenJoined); + theArrPeriods, aCheckResult, hasBeenJoined); } if(hasBeenJoined) diff --git a/src/IntPatch/IntPatch_WLineTool.hxx b/src/IntPatch/IntPatch_WLineTool.hxx index 02e4584a10..9a40853f9b 100644 --- a/src/IntPatch/IntPatch_WLineTool.hxx +++ b/src/IntPatch/IntPatch_WLineTool.hxx @@ -14,17 +14,11 @@ #ifndef _IntPatch_WLineTool_HeaderFile #define _IntPatch_WLineTool_HeaderFile -#include -#include -#include #include -#include -class TopoDS_Face; -class GeomAdaptor_HSurface; -class GeomInt_LineConstructor; -class IntTools_Context; +#include +#include + class Adaptor3d_TopolTool; -class Adaptor3d_HSurface; //! IntPatch_WLineTool provides set of static methods related to walking lines. class IntPatch_WLineTool @@ -84,20 +78,21 @@ public: //! in strictly determined point (in the place of joint of two lines). //! As result, some gaps between two lines will vanish. //! The Walking lines are supposed (algorithm will do nothing for not-Walking line) -//! to be computed as a result of intersection of two quadrics. -//! The quadrics definition is accepted in input parameters. - Standard_EXPORT static void ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin, - const IntSurf_Quadric& theS1, - const IntSurf_Quadric& theS2, - const Standard_Real theToler3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - const Bnd_Box2d& theBoxS1, - const Bnd_Box2d& theBoxS2); +//! to be computed as a result of intersection. Both theS1 and theS2 +//! must be quadrics. Other cases are not supported. +//! theArrPeriods must be filled as follows: +//! {, , +//! , }. + Standard_EXPORT static void + ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin, + const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const Standard_Real theToler3D, + const Standard_Real* const theArrPeriods, + const Bnd_Box2d& theBoxS1, + const Bnd_Box2d& theBoxS2); -//! Max angle to concatenate two WLines to avoid result with C0-continuity + //! Max angle to concatenate two WLines to avoid result with C0-continuity static const Standard_Real myMaxConcatAngle; }; diff --git a/src/IntSurf/IntSurf.cxx b/src/IntSurf/IntSurf.cxx index 86ff1be3b8..d1d8e5c2af 100644 --- a/src/IntSurf/IntSurf.cxx +++ b/src/IntSurf/IntSurf.cxx @@ -12,13 +12,12 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - -#include -#include -#include #include + +#include #include #include +#include //-------------------------------------------------------------- //-- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc); @@ -98,7 +97,18 @@ void IntSurf::MakeTransition (const gp_Vec& TgFirst, } } - - +//======================================================================= +//function : SetPeriod +//purpose : +//======================================================================= +void IntSurf::SetPeriod(const Handle(Adaptor3d_HSurface)& theFirstSurf, + const Handle(Adaptor3d_HSurface)& theSecondSurf, + Standard_Real theArrOfPeriod[4]) +{ + theArrOfPeriod[0] = theFirstSurf->IsUPeriodic()? theFirstSurf->UPeriod() : 0.0; + theArrOfPeriod[1] = theFirstSurf->IsVPeriodic()? theFirstSurf->VPeriod() : 0.0; + theArrOfPeriod[2] = theSecondSurf->IsUPeriodic()? theSecondSurf->UPeriod() : 0.0; + theArrOfPeriod[3] = theSecondSurf->IsVPeriodic()? theSecondSurf->VPeriod() : 0.0; +} diff --git a/src/IntSurf/IntSurf.hxx b/src/IntSurf/IntSurf.hxx index 6448b6b814..80890c8166 100644 --- a/src/IntSurf/IntSurf.hxx +++ b/src/IntSurf/IntSurf.hxx @@ -17,24 +17,13 @@ #ifndef _IntSurf_HeaderFile #define _IntSurf_HeaderFile -#include #include #include -class gp_Vec; +class Adaptor3d_HSurface; +class IntSurf_Transition; class gp_Dir; -class IntSurf_Transition; -class IntSurf_PntOn2S; -class IntSurf_Couple; -class IntSurf_LineOn2S; -class IntSurf_Quadric; -class IntSurf_QuadricTool; -class IntSurf_PathPoint; -class IntSurf_PathPointTool; -class IntSurf_InteriorPoint; -class IntSurf_InteriorPointTool; -class IntSurf_Transition; - +class gp_Vec; //! This package provides resources for //! all the packages concerning the intersection @@ -56,6 +45,17 @@ public: //! TSecond is the transition of the point on the second line. Standard_EXPORT static void MakeTransition (const gp_Vec& TgFirst, const gp_Vec& TgSecond, const gp_Dir& Normal, IntSurf_Transition& TFirst, IntSurf_Transition& TSecond); + //! Fills theArrOfPeriod array by the period values of theFirstSurf and theSecondSurf. + //! [0] = U-period of theFirstSurf, + //! [1] = V-period of theFirstSurf, + //! [2] = U-period of theSecondSurf, + //! [3] = V-period of theSecondSurf. + //! + //! If surface is not periodic in correspond direction then + //! its period is considered to be equal to 0. + Standard_EXPORT static void SetPeriod(const Handle(Adaptor3d_HSurface)& theFirstSurf, + const Handle(Adaptor3d_HSurface)& theSecondSurf, + Standard_Real theArrOfPeriod[4]); diff --git a/src/IntTools/IntTools_FaceFace.cxx b/src/IntTools/IntTools_FaceFace.cxx index 166b4f15a6..ce8f3712f9 100644 --- a/src/IntTools/IntTools_FaceFace.cxx +++ b/src/IntTools/IntTools_FaceFace.cxx @@ -15,100 +15,45 @@ #include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include - -#include -#include -#include -#include -#include -#include - #include #include #include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include - -#include -#include -#include #include -#include +#include +#include +#include +#include +#include static void TolR3d(const TopoDS_Face& , @@ -1333,183 +1278,8 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index, }// IntPatch_Circle: IntPatch_Ellipse: break; - case IntPatch_Analytic: { - IntSurf_Quadric quad1,quad2; - GeomAbs_SurfaceType typs = myHS1->Surface().GetType(); - - switch (typs) { - case GeomAbs_Plane: - quad1.SetValue(myHS1->Surface().Plane()); - break; - case GeomAbs_Cylinder: - quad1.SetValue(myHS1->Surface().Cylinder()); - break; - case GeomAbs_Cone: - quad1.SetValue(myHS1->Surface().Cone()); - break; - case GeomAbs_Sphere: - quad1.SetValue(myHS1->Surface().Sphere()); - break; - case GeomAbs_Torus: - quad1.SetValue(myHS1->Surface().Torus()); - break; - default: - Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 1"); - } - - typs = myHS2->Surface().GetType(); - - switch (typs) { - case GeomAbs_Plane: - quad2.SetValue(myHS2->Surface().Plane()); - break; - case GeomAbs_Cylinder: - quad2.SetValue(myHS2->Surface().Cylinder()); - break; - case GeomAbs_Cone: - quad2.SetValue(myHS2->Surface().Cone()); - break; - case GeomAbs_Sphere: - quad2.SetValue(myHS2->Surface().Sphere()); - break; - case GeomAbs_Torus: - quad2.SetValue(myHS2->Surface().Torus()); - break; - default: - Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve 2"); - } - // - //========= - IntPatch_ALineToWLine convert (quad1, quad2); - - if (!myApprox) { - aNbParts=myLConstruct.NbParts(); - for (i=1; i<=aNbParts; i++) { - myLConstruct.Part(i, fprm, lprm); - Handle(IntPatch_WLine) WL = - convert.MakeWLine(Handle(IntPatch_ALine)::DownCast(L), fprm, lprm); - // - Handle(Geom2d_BSplineCurve) H1; - Handle(Geom2d_BSplineCurve) H2; - - if(myApprox1) { - H1 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True); - } - - if(myApprox2) { - H2 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False); - } - // - mySeqOfCurve.Append(IntTools_Curve(GeomInt_IntSS::MakeBSpline(WL,1,WL->NbPnts()), H1, H2)); - } - } // if (!myApprox) - - else { // myApprox=TRUE - GeomInt_WLApprox theapp3d; - // - Standard_Real tol2d = myTolApprox; - // - theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True); - - aNbParts=myLConstruct.NbParts(); - for (i=1; i<=aNbParts; i++) { - myLConstruct.Part(i, fprm, lprm); - Handle(IntPatch_WLine) WL = - convert.MakeWLine(Handle(IntPatch_ALine):: DownCast(L),fprm,lprm); - - theapp3d.Perform(myHS1,myHS2,WL,Standard_True,myApprox1,myApprox2, 1, WL->NbPnts()); - - if (!theapp3d.IsDone()) { - // - Handle(Geom2d_BSplineCurve) H1; - Handle(Geom2d_BSplineCurve) H2; - - if(myApprox1) { - H1 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True); - } - - if(myApprox2) { - H2 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False); - } - // - mySeqOfCurve.Append(IntTools_Curve(GeomInt_IntSS::MakeBSpline(WL,1,WL->NbPnts()), H1, H2)); - } - - else { - if(myApprox1 || myApprox2) { - if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0) { - myTolReached2d = theapp3d.TolReached2d(); - } - } - - if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0) { - myTolReached3d = theapp3d.TolReached3d(); - } - - Standard_Integer aNbMultiCurves, nbpoles; - aNbMultiCurves=theapp3d.NbMultiCurves(); - for (j=1; j<=aNbMultiCurves; j++) { - const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j); - nbpoles = mbspc.NbPoles(); - - TColgp_Array1OfPnt tpoles(1, nbpoles); - mbspc.Curve(1, tpoles); - Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK); - Check.FixTangent(Standard_True,Standard_True); - // - IntTools_Curve aCurve; - aCurve.SetCurve(BS); - - if(myApprox1) { - TColgp_Array1OfPnt2d tpoles2d(1,nbpoles); - mbspc.Curve(2,tpoles2d); - Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK); - newCheck.FixTangent(Standard_True,Standard_True); - // - aCurve.SetFirstCurve2d(BS2); - } - else { - Handle(Geom2d_BSplineCurve) H1; - aCurve.SetFirstCurve2d(H1); - } - - if(myApprox2) { - TColgp_Array1OfPnt2d tpoles2d(1, nbpoles); - Standard_Integer TwoOrThree; - TwoOrThree=myApprox1 ? 3 : 2; - mbspc.Curve(TwoOrThree, tpoles2d); - Handle(Geom2d_BSplineCurve) BS2 =new Geom2d_BSplineCurve(tpoles2d, - mbspc.Knots(), - mbspc.Multiplicities(), - mbspc.Degree()); - - GeomLib_Check2dBSplineCurve newCheck(BS2,TOLCHECK,TOLANGCHECK); - newCheck.FixTangent(Standard_True,Standard_True); - // - aCurve.SetSecondCurve2d(BS2); - } - else { - Handle(Geom2d_BSplineCurve) H2; - aCurve.SetSecondCurve2d(H2); - } - // - mySeqOfCurve.Append(aCurve); - - }// for (j=1; j<=aNbMultiCurves; j++) { - }// else from if (!theapp3d.IsDone()) - }// for (i=1; i<=aNbParts; i++) { - }// else { // myApprox=TRUE - }// case IntPatch_Analytic: + case IntPatch_Analytic: + //This case was processed earlier (in IntPatch_Intersection) break; case IntPatch_Walking:{ diff --git a/src/IntTools/IntTools_Tools.cxx b/src/IntTools/IntTools_Tools.cxx index c6a71f3ca8..a6b39755cd 100644 --- a/src/IntTools/IntTools_Tools.cxx +++ b/src/IntTools/IntTools_Tools.cxx @@ -805,7 +805,7 @@ Standard_Boolean IntTools_Tools::ComputeTolerance //e.g. after trimming) we will be able to come //to the more precise minimum point. As result, this curve with the //tolerance computed earlier will become invalid. - const Standard_Real anEps = (1.0+1.0e-9); + const Standard_Real anEps = (1.0+1.0e-7); theMaxDist = anEps*aCS.MaxDistance(); theMaxPar = aCS.MaxParameter(); // diff --git a/src/TopOpeBRep/TopOpeBRep_LineInter.cxx b/src/TopOpeBRep/TopOpeBRep_LineInter.cxx index edabcd5c0f..892229a627 100644 --- a/src/TopOpeBRep/TopOpeBRep_LineInter.cxx +++ b/src/TopOpeBRep/TopOpeBRep_LineInter.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -50,49 +51,28 @@ #include #include +#include + #ifdef OCCT_DEBUG extern Standard_Boolean TopOpeBRep_GetcontextALWLNBP(Standard_Integer&); extern Standard_Boolean TopOpeBRep_GettraceCONIC(); #endif //----------------------------------------------------------------------- -static Handle(IntPatch_WLine) FUN_ALINETOWLINE -(const Handle(IntPatch_ALine)& AL, - const BRepAdaptor_Surface surf1,const BRepAdaptor_Surface surf2) -//----------------------------------------------------------------------- +static void FUN_ALINETOWLINE (const Handle(IntPatch_ALine)& AL, + const Handle(BRepAdaptor_HSurface) surf1, + const Handle(BRepAdaptor_HSurface) surf2, + IntPatch_SequenceOfLine& theLines) { - IntSurf_Quadric Quad1,Quad2; - - switch(surf1.GetType()) - { - case GeomAbs_Plane: Quad1.SetValue(surf1.Plane()); break; - case GeomAbs_Cylinder: Quad1.SetValue(surf1.Cylinder()); break; - case GeomAbs_Sphere: Quad1.SetValue(surf1.Sphere()); break; - case GeomAbs_Cone: Quad1.SetValue(surf1.Cone()); break; - default : Standard_ProgramError::Raise - ("TopOpeBRep_LineInter::FUN_ALINETOWLINE"); break; - } - - switch(surf2.GetType()) - { - case GeomAbs_Plane: Quad2.SetValue(surf2.Plane()); break; - case GeomAbs_Cylinder: Quad2.SetValue(surf2.Cylinder()); break; - case GeomAbs_Sphere: Quad2.SetValue(surf2.Sphere()); break; - case GeomAbs_Cone: Quad2.SetValue(surf2.Cone()); break; - default : Standard_ProgramError::Raise - ("TopOpeBRep_LineInter::FUN_ALINETOWLINE"); break; - } - - const Standard_Real deflectionmax = 0.01; - const Standard_Real pasUVmax = 0.05; Standard_Integer nbpointsmax = 200; #ifdef OCCT_DEBUG Standard_Integer newnbp; if (TopOpeBRep_GetcontextALWLNBP(newnbp)) nbpointsmax = newnbp; #endif IntPatch_ALineToWLine - AToL(Quad1,Quad2,deflectionmax,pasUVmax,nbpointsmax); - return AToL.MakeWLine(AL); + AToL(surf1,surf2,nbpointsmax); + + AToL.MakeWLine(AL, theLines); } //======================================================================= @@ -135,7 +115,13 @@ void TopOpeBRep_LineInter::SetLine(const Handle(IntPatch_Line)& L, // transform an analytic line to a walking line if (myTypeLineCurve == TopOpeBRep_ANALYTIC) { - myILW = ::FUN_ALINETOWLINE(myILA,S1,S2); + IntPatch_SequenceOfLine aSLin; + FUN_ALINETOWLINE(myILA,new BRepAdaptor_HSurface(S1), + new BRepAdaptor_HSurface(S2), aSLin); + + if(aSLin.Length() > 0) + myILW = Handle(IntPatch_WLine)::DownCast(aSLin.Value(1)); + myTypeLineCurve = TopOpeBRep_WALKING; } diff --git a/tests/bugs/modalg_4/bug62 b/tests/bugs/modalg_4/bug62 index 3341ee647c..ed7e59da8f 100755 --- a/tests/bugs/modalg_4/bug62 +++ b/tests/bugs/modalg_4/bug62 @@ -1,6 +1,3 @@ -puts "TODO OCC25735 ALL: Faulty shapes in variables faulty_1 to" -puts "TODO OCC22033 ALL: Error : The area of result shape is" - puts "================" puts "OCC62" puts "BUC61001" @@ -32,5 +29,5 @@ checkshape res5 renamevar res5 result -checkprops result -s 1.23063e+7 +checkprops result -s 1.20915e+007 checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_4/bug826 b/tests/bugs/modalg_4/bug826 index f31416efa5..166c3e5790 100755 --- a/tests/bugs/modalg_4/bug826 +++ b/tests/bugs/modalg_4/bug826 @@ -7,7 +7,16 @@ puts "" ################################### ## BRepAlgoAPI_Fuse fails on revolved and sphere ################################### -## (old topology) +## Now this test uses BOPAlgo. +## Intersection of cylinder and sphere. At that, +## the intersection line goes near to the pole +## of the sphere (near, but not through). +## Walking-line has a point in the seam of +## the sphere and neighbour point. Both sections of the +## sphere (through every of these points and parallel to +## equatorial plane) are circles with small radii. As result, +## in 2D-space U-coordinates of these points are too different +## (may be even ~60 degrees) in spite of its neighbourhood. ##################################### if { [ catch { set info_result [OCC826 a1 a2 result] } ] } { @@ -23,6 +32,6 @@ if { [ catch { set info_result [OCC826 a1 a2 result] } ] } { } } -checkprops result -s 272939 +checkprops result -s 272935 checkshape result checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_4/bug826_1 b/tests/bugs/modalg_4/bug826_1 index c23847802d..e41a1c7faa 100755 --- a/tests/bugs/modalg_4/bug826_1 +++ b/tests/bugs/modalg_4/bug826_1 @@ -7,10 +7,17 @@ puts "" ################################### ## BRepAlgoAPI_Fuse fails on revolved and sphere ################################### -## -## Note: test for old topology -## -################################ +## Now this test uses BOPAlgo. +## Intersection of cylinder and sphere. At that, +## the intersection line goes near to the pole +## of the sphere (near, but not through). +## Walking-line has a point in the seam of +## the sphere and neighbour point. Both sections of the +## sphere (through every of these points and parallel to +## equatorial plane) are circles with small radii. As result, +## in 2D-space U-coordinates of these points are too different +## (may be even ~60 degrees) in spite of its neighbourhood. +##################################### if { [ catch { set result [OCC826 a1 a2 a3] } ] } { puts "Faulty : an exception was caught" @@ -25,6 +32,6 @@ if { [ catch { set result [OCC826 a1 a2 a3] } ] } { } } -checkprops result -s 272939 +checkprops result -s 272935 checkshape result checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_5/bug25292_33 b/tests/bugs/modalg_5/bug25292_33 index 7fcd7aea75..4c9a5cafb3 100644 --- a/tests/bugs/modalg_5/bug25292_33 +++ b/tests/bugs/modalg_5/bug25292_33 @@ -6,27 +6,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -49,60 +28,37 @@ intersect res s1 s2 set che [whatis res] set ind [string first "3d curve" $che] + +set AllowRepeate 1 +set ic 1 + if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" + renamevar res res_1 +} + +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 + break } - set U1 0.0 - set U2 0.0 + bounds res_$ic U1 U2 - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval (U2-U1)] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs res s1 ${U1} ${U2} 10 1e-6 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-6 1e-7 -} else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-6 1e-7 - xdistcs res_$ic s2 0 1 10 1e-6 1e-7 - - incr ic - } - } + xdistcs res_$ic s1 U1 U2 10 1e-6 1e-7 + xdistcs res_$ic s2 U1 U2 10 1e-6 1e-7 - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } + incr ic } + +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Good number of intersection curve(s) obtained by Surface/Surface Intersection Algorithm" +} else { + puts "Error: $GoodNbCurv intersection curve(s) expected but [expr {$ic - 1}] found" +} \ No newline at end of file diff --git a/tests/bugs/modalg_5/bug25292_34 b/tests/bugs/modalg_5/bug25292_34 index 0266bbbed8..9d23d65990 100644 --- a/tests/bugs/modalg_5/bug25292_34 +++ b/tests/bugs/modalg_5/bug25292_34 @@ -1,3 +1,4 @@ + puts "================" puts "OCC25292" puts "================" @@ -6,27 +7,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -49,60 +29,37 @@ intersect res s2 s1 set che [whatis res] set ind [string first "3d curve" $che] + +set AllowRepeate 1 +set ic 1 + if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" + renamevar res res_1 +} + +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 + break } - set U1 0.0 - set U2 0.0 + bounds res_$ic U1 U2 - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval (U2-U1)] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs res s1 ${U1} ${U2} 10 1e-6 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-6 1e-7 -} else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-6 1e-7 - xdistcs res_$ic s2 0 1 10 1e-6 1e-7 - - incr ic - } - } + xdistcs res_$ic s1 U1 U2 10 1e-6 1e-7 + xdistcs res_$ic s2 U1 U2 10 1e-6 1e-7 - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } + incr ic } + +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Good number of intersection curve(s) obtained by Surface/Surface Intersection Algorithm" +} else { + puts "Error: $GoodNbCurv intersection curve(s) expected but [expr {$ic - 1}] found" +} \ No newline at end of file diff --git a/tests/bugs/modalg_5/bug25319_1 b/tests/bugs/modalg_5/bug25319_1 index 48038e0bbc..fc35232bf6 100644 --- a/tests/bugs/modalg_5/bug25319_1 +++ b/tests/bugs/modalg_5/bug25319_1 @@ -6,6 +6,8 @@ puts "" # Bop Common produces strange results with same shapes. ######################################################################## +puts "TODO #OCC27896 ALL: Faulty shapes in variables faulty_1 to faulty_" + restore [locate_data_file bug25319_S1.brep] b1 restore [locate_data_file bug25319_S2.brep] b2 diff --git a/tests/bugs/modalg_5/bug25319_2 b/tests/bugs/modalg_5/bug25319_2 index ecca179825..60cf73ecb8 100644 --- a/tests/bugs/modalg_5/bug25319_2 +++ b/tests/bugs/modalg_5/bug25319_2 @@ -6,6 +6,8 @@ puts "" # Bop Common produces strange results with same shapes. ######################################################################## +puts "TODO #OCC27896 ALL: Faulty shapes in variables faulty_1 to faulty_" + restore [locate_data_file bug25319_S1.brep] b1 restore [locate_data_file bug25319_S2.brep] b2 diff --git a/tests/bugs/modalg_5/bug25838 b/tests/bugs/modalg_5/bug25838 index c499c8b7e5..708889e074 100644 --- a/tests/bugs/modalg_5/bug25838 +++ b/tests/bugs/modalg_5/bug25838 @@ -6,6 +6,7 @@ puts "" # Wrong result obtained by General Fuse operator. ############################################### puts "TODO #OCC26816 ALL: Error : Result done by General Fuse operator is WRONG because number of" +puts "TODO #OCC26816 ALL: Faulty shapes in variables faulty_1 to faulty_" restore [locate_data_file bug25715_p02c3s1.brep] b1 restore [locate_data_file bug25838_p02c3s2.brep] b2 diff --git a/tests/bugs/modalg_6/bug27282_2 b/tests/bugs/modalg_6/bug27282_2 index da6fbca1b6..0fb4de1ef2 100644 --- a/tests/bugs/modalg_6/bug27282_2 +++ b/tests/bugs/modalg_6/bug27282_2 @@ -6,7 +6,7 @@ puts "" ## [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape ############################### -set MaxTol 4.8106952270863644e-006 +set MaxTol 3.8178537637632889e-006 set GoodNbCurv 1 restore [locate_data_file bug27282_cmpd.brep] a diff --git a/tests/bugs/modalg_6/bug27302 b/tests/bugs/modalg_6/bug27302 index efd39e59aa..14f0396bd9 100644 --- a/tests/bugs/modalg_6/bug27302 +++ b/tests/bugs/modalg_6/bug27302 @@ -6,7 +6,7 @@ puts "" ## Invalid curves number in intersection result ############################### -set MaxTol 9.9579577516847715e-005 +set MaxTol 6.899054167648517e-007 set GoodNbCurv 1 restore [locate_data_file CTO900_pro12913a.rle] a diff --git a/tests/bugs/modalg_6/bug27431 b/tests/bugs/modalg_6/bug27431 new file mode 100644 index 0000000000..311bafb60c --- /dev/null +++ b/tests/bugs/modalg_6/bug27431 @@ -0,0 +1,67 @@ +puts "============" +puts "OCC27431" +puts "============" +puts "" +############################### +## [Regression to 6.9.1] Huge tolerance obtained during intersection of cylinder and sphere +############################### + +pload ALL + +set MaxTol1 0.00042926432143107718 +set MaxTol2 0.00042926432143107718 + +set GoodNbCurv 4 + +restore [locate_data_file OCC13116_sh1.brep] b1 +restore [locate_data_file OCC13116_sh2.brep] b2 + +explode b1 f +explode b2 f + +set log1 [bopcurves b1_3 b2_1 -2d] + +regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log1} full Toler NbCurv + +# Before fixing: Tolerance Reached=27.904993728420369 +checkreal ToleranceReached ${Toler} ${MaxTol1} 0.0 0.01 + +smallview +don b1_3 b2_1 c_* +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}_3d_1.png + +v2d +don c2d* +2dfit +checkview -screenshot -2d -path ${imagedir}/${test_image}_2d_1.png + +if {${NbCurv} != ${GoodNbCurv}} { + puts "Error: Number of curves is bad!" +} + +# increasing tolerance values of the faces on Precision::Confusion() +# dramatically increased (before fixing) the tolerance of +# the produced section curves + +settolerance b1_3 2.34623727264857e-007 +settolerance b2_1 2.e-7 + +set log2 [bopcurves b1_3 b2_1 -2d] + +regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log2} full Toler NbCurv + +# Before fixing: Tolerance Reached=40.000000093341022 +checkreal ToleranceReached ${Toler} ${MaxTol2} 0.0 0.01 + +smallview +don b1_3 b2_1 c_* +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}_3d_2.png + +v2d +don c2d* +2dfit +checkview -screenshot -2d -path ${imagedir}/${test_image}_2d_2.png diff --git a/tests/bugs/moddata_2/bug565 b/tests/bugs/moddata_2/bug565 index ae63aaddbf..b47478754f 100755 --- a/tests/bugs/moddata_2/bug565 +++ b/tests/bugs/moddata_2/bug565 @@ -3,51 +3,71 @@ puts "========| OCC565 |========" ## Can not intersect two trimmed conical surfaces ################################## +puts "TODO OCC28016 Linux: Error: 1 is expected but .* is found!" + +set GoodNbCurv 1 + +foreach c [directory result*] { + unset $c +} + +foreach c [directory inf*] { + unset $c +} + restore [locate_data_file OCC565a.draw] s1 restore [locate_data_file OCC565b.draw] s2 puts "Preliminary check: intersection work with infinite cones:" if { [catch {intersect inf s1 s2 } catch_result] } { - puts "Faulty OCC565: function intersection works wrongly with infinite cones" + puts "Faulty OCC565: function intersection works wrongly with infinite cones" } else { - set j 1 - set er [lindex [whatis inf] 5] - repeat 4 { - set err [lindex [whatis inf_$j] 5] - if { $err != "curve" && $er != "curve"} { - puts " Faulty OCC565: function intersection works wrongly with infinite cones" - break - } else { - puts [format "curve inf_%s : exist " $j] - } - incr j + set isFound 0 + foreach c [directory inf*] { + set ind [string first "3d curve" [whatis $c]] + if {${ind} < 0} { + dump $c + puts "Error: Intersection result (with infinite cones) is not 3D-curve" + } else { + set isFound 1 } - puts "Function intersection works correctly with infinite cones. Then check OCC565:" + } + + if { !$isFound } { + puts "Error: Empty intersection result (with infinite cones)" + } } trim s1x s1 0 2*pi 0 2.8 trim s2x s2 0 2*pi 0 2.8 if { [catch {intersect result s1x s2x } catch_result] } { - puts "Faulty OCC565 exception: function intersection works wrongly with trimmed cones" + puts "Faulty OCC565 exception: function intersection works wrongly with trimmed cones" } else { - set nom 0 - set j 1 - set er [lindex [whatis result] 5] - repeat 4 { - set err [lindex [whatis result_$j] 5] - if { $err != "curve" && $er != "curve"} { - break - } else { - set nom [expr $nom + 1] - } - incr j - } - if { $nom == 0} { - puts " Faulty OCC565: function intersection works wrongly with trimmed cones" - } else { - puts " OCC565 OK: function intersection works with trimmed cones" + foreach c [directory result*] { + bounds $c U1 U2 + + if {[dval U2-U1] < 1.0e-9} { + puts "Error: Wrong curve's range!" } + + xdistcs $c s1 U1 U2 10 1.0e-7 + xdistcs $c s2 U1 U2 10 1.0e-7 + } + + set NbCurv [llength [directory result*]] + + if { $NbCurv == $GoodNbCurv } { + puts "OK: Number of curves is good!" + } else { + puts "Error: $GoodNbCurv is expected but $NbCurv is found!" + } + + smallview + don result* + fit + disp s1x s2x + checkview -screenshot -2d -path ${imagedir}/${test_image}.png } diff --git a/tests/bugs/moddata_3/bug23981 b/tests/bugs/moddata_3/bug23981 index 5fbce92383..2c6925494d 100755 --- a/tests/bugs/moddata_3/bug23981 +++ b/tests/bugs/moddata_3/bug23981 @@ -12,10 +12,10 @@ restore [locate_data_file bug23981_s2.draw] s2 intersect i s1 s2 puts "First test" -xdistcs i_1 s1 0 1 100 1e-5 +xdistcs i_1 s1 0 1 100 1e-7 puts "Second test" -xdistcs i_2 s1 0 1 100 1e-5 +xdistcs i_2 s1 0 1 100 1e-7 smallview fit