Standard_Real theFleche=0;
Standard_Boolean flecheok = Standard_False;
if (Norme > Eps) {
- // Evaluation of the arrow by interpolation. See IntWalk_IWalking_5.gxx
+ // Evaluation of the arrow by interpolation. See IntWalk_IWalking::TestDeflection
Standard_Real N1 = Vdeb.SquareMagnitude();
Standard_Real N2 = Vdelta.SquareMagnitude();
if (N1 > Eps && N2 > Eps) {
Standard_Boolean isFlecheOk = Standard_False;
if (aNorme > theEps && aNorme > 16. * theDeflection2)
{
- // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking_5.gxx
+ // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking::TestDeflection
Standard_Real N1 = theVdeb.SquareMagnitude();
Standard_Real N2 = aVdelta.SquareMagnitude();
if (N1 > theEps && N2 > theEps)
IntPatch_ImpImpIntersection.cxx
IntPatch_ImpImpIntersection.hxx
IntPatch_ImpImpIntersection.lxx
-IntPatch_ImpImpIntersection_0.gxx
-IntPatch_ImpImpIntersection_1.gxx
-IntPatch_ImpImpIntersection_2.gxx
-IntPatch_ImpImpIntersection_3.gxx
-IntPatch_ImpImpIntersection_4.gxx
-IntPatch_ImpImpIntersection_5.gxx
-IntPatch_ImpImpIntersection_6.gxx
IntPatch_ImpPrmIntersection.cxx
IntPatch_ImpPrmIntersection.hxx
IntPatch_ImpPrmIntersection.lxx
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
+// Copyright (c) 1999-2024 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-
#include <Adaptor2d_Curve2d.hxx>
-#include <Adaptor3d_Surface.hxx>
#include <Adaptor3d_HVertex.hxx>
+#include <Adaptor3d_Surface.hxx>
#include <Adaptor3d_TopolTool.hxx>
+#include <Bnd_Box2d.hxx>
+#include <Bnd_Range.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
-#include <gp.hxx>
-#include <gp_Cone.hxx>
-#include <gp_Cylinder.hxx>
-#include <gp_Pln.hxx>
-#include <gp_Sphere.hxx>
+#include <Extrema_ExtPC.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <Geom_Ellipse.hxx>
+#include <Geom_Hyperbola.hxx>
+#include <Geom_Parabola.hxx>
#include <IntAna_IntQuadQuad.hxx>
+#include <IntAna_ListOfCurve.hxx>
#include <IntAna_QuadQuadGeo.hxx>
#include <IntAna_Quadric.hxx>
#include <IntPatch_ALine.hxx>
#include <IntPatch_GLine.hxx>
#include <IntPatch_HInterTool.hxx>
#include <IntPatch_ImpImpIntersection.hxx>
-#include "../IntPatch/IntPatch_ImpImpIntersection_0.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_1.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_2.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_3.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_4.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_5.gxx"
-#include "../IntPatch/IntPatch_ImpImpIntersection_6.gxx"
-#include <IntPatch_Line.hxx>
-#include <IntPatch_Point.hxx>
#include <IntPatch_RLine.hxx>
-#include <IntPatch_SequenceOfLine.hxx>
#include <IntPatch_ThePathPointOfTheSOnBounds.hxx>
#include <IntPatch_TheSegmentOfTheSOnBounds.hxx>
+#include <IntPatch_WLine.hxx>
#include <IntSurf.hxx>
-#include <IntSurf_Quadric.hxx>
-#include <Standard_ConstructionError.hxx>
-#include <Standard_DomainError.hxx>
-#include <Standard_OutOfRange.hxx>
-#include <StdFail_NotDone.hxx>
-#include <TColgp_SequenceOfPnt.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <Standard_DivideByZero.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_SequenceOfReal.hxx>
+#include <gce_MakeLin.hxx>
+#include <gp.hxx>
+#include <gp_Cone.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Sphere.hxx>
+#include <math_Matrix.hxx>
+#include <math_Vector.hxx>
+
+#include <algorithm>
+
+static void PutPointsOnLine(const Handle(Adaptor3d_Surface)& S1,
+ const Handle(Adaptor3d_Surface)& S2,
+ const IntPatch_SequenceOfPathPointOfTheSOnBounds&,
+ const IntPatch_SequenceOfLine&,
+ const Standard_Boolean,
+ const Handle(Adaptor3d_TopolTool)&,
+ const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Boolean,
+ const Standard_Real);
+
+static Standard_Boolean MultiplePoint(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
+ const Handle(Adaptor3d_TopolTool)& Domain,
+ const IntSurf_Quadric& QuadSurf,
+ const gp_Vec& Normale,
+ const IntPatch_SequenceOfLine& slin,
+ TColStd_Array1OfInteger& Done,
+ TColStd_Array1OfInteger& UsedLine,
+ const Standard_Integer Index,
+ const Standard_Boolean OnFirst,
+ const Standard_Real theToler);
+
+static Standard_Boolean PointOnSecondDom(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
+ const Handle(Adaptor3d_TopolTool)& Domain,
+ const IntSurf_Quadric& QuadSurf,
+ const gp_Vec& Normale,
+ const gp_Vec& Vtgint,
+ const Handle(IntPatch_Line)& lin,
+ TColStd_Array1OfInteger& Done,
+ const Standard_Integer Index,
+ const Standard_Real theToler);
+
+static Standard_Boolean SingleLine(const gp_Pnt&, const Handle(IntPatch_Line)&, const Standard_Real, Standard_Real&, gp_Vec&);
+
+static Standard_Boolean FindLine(gp_Pnt& Psurf,
+ const IntPatch_SequenceOfLine& slin,
+ const Standard_Real Tol,
+ TColStd_ListOfReal& theLParams,
+ gp_Vec& Vtgtint,
+ Standard_Integer& theLineIdx,
+ Standard_Integer OnlyThisLine,
+ const Handle(Adaptor2d_Curve2d)& thearc,
+ Standard_Real& theparameteronarc,
+ gp_Pnt& thepointonarc,
+ const IntSurf_Quadric& QuadSurf1,
+ const IntSurf_Quadric& QuadSurf2,
+ Standard_Real& theOutputToler);
+
+static void ProcessSegments(const IntPatch_SequenceOfSegmentOfTheSOnBounds&,
+ IntPatch_SequenceOfLine&,
+ const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Boolean,
+ const Standard_Real);
+
+static void ProcessRLine(IntPatch_SequenceOfLine&,
+ const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean theIsReqToKeepRLine);
+
+//-- le calcul de dist est completement faux ds la routine ci dessous a revoir (lbr le 18 nov 97)
+Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf,
+ const Handle(IntPatch_ALine)& alin,
+ Standard_Real& para,
+ const Handle(Adaptor2d_Curve2d)& thearc,
+ Standard_Real& _theparameteronarc,
+ gp_Pnt& thepointonarc,
+ const IntSurf_Quadric& QuadSurf,
+ const Standard_Real u0alin,
+ const Standard_Real u1alin)
+{
+ Standard_Real dtheta, theta;
+#ifdef OCCT_DEBUG
+ //Standard_Real u,v,A,B,C,cost,sint,sign;
+#endif
+ //-- recherche bete du point le plus proche de thearc->Value(...)
+ dtheta = (u1alin - u0alin) * 0.01;
+ Standard_Real du = 0.000000001;
+ if (du >= dtheta)
+ du = dtheta / 2;
+ Standard_Real distmin = RealLast();
+
+ Standard_Real thetamin = 0.;
+
+ Standard_Real theparameteronarc = _theparameteronarc;
+ for (Standard_Real _theta = u0alin + dtheta; _theta <= u1alin - dtheta; _theta += dtheta)
+ {
+ gp_Pnt P = alin->Value(_theta);
+ Standard_Real d = P.Distance(PSurf);
+ if (d < distmin)
+ {
+ thetamin = _theta;
+ distmin = d;
+ }
+ }
+
+ Standard_Real bestpara = 0., besttheta = 0., bestdist = 0., distinit = 0.;
+
+ //-- Distance initiale
+ {
+ gp_Pnt pp0 = alin->Value(thetamin);
+ Standard_Real ua0, va0;
+ QuadSurf.Parameters(pp0, ua0, va0);
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+ thearc->D1(theparameteronarc, p2d, d2d);
+ gp_Vec2d PaPr(gp_Pnt2d(ua0, va0), p2d);
+ distinit = PaPr.Magnitude();
+ }
+ theta = thetamin;
+ //-- recherche a partir de theta et theparameteronarc
+ Standard_Boolean cpasok = Standard_True;
+ Standard_Integer nbiter = 0;
+ Standard_Real drmax = (thearc->LastParameter() - thearc->FirstParameter()) * 0.05;
+ Standard_Real damax = (u1alin - u0alin) * 0.05;
+
+ bestdist = RealLast();
+
+ do
+ {
+ Standard_Real ua0, va0, ua1, va1;
+ //-- alin->Curve().InternalUVValue(theta,ua0,va0,A,B,C,cost,sint,sign);
+ //-- alin->Curve().InternalUVValue(theta+du,ua1,va1,A,B,C,cost,sint,sign);
+ gp_Pnt pp0 = alin->Value(theta);
+ gp_Pnt pp1 = alin->Value(theta + du);
+ QuadSurf.Parameters(pp0, ua0, va0);
+ QuadSurf.Parameters(pp1, ua1, va1);
+
+ gp_Vec2d D1a((ua1 - ua0) / du, (va1 - va0) / du);
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+ thearc->D1(theparameteronarc, p2d, d2d);
+ gp_Vec2d PaPr(gp_Pnt2d(ua0, va0), p2d);
+
+ Standard_Real pbd = PaPr.Magnitude();
+ if (bestdist > pbd)
+ {
+ bestdist = pbd;
+ bestpara = theparameteronarc;
+ besttheta = theta;
+ }
+
+ D1a.SetCoord(-D1a.X(), -D1a.Y());
+
+ Standard_Real d = D1a.X() * d2d.Y() - D1a.Y() * d2d.X();
+
+ Standard_Real da = (-PaPr.X()) * d2d.Y() - (-PaPr.Y()) * d2d.X();
+ Standard_Real dr = D1a.X() * (-PaPr.Y()) - D1a.Y() * (-PaPr.X());
+ if (Abs(d) > 1e-15)
+ {
+ da /= d;
+ dr /= d;
+ }
+ else
+ {
+ if (Abs(PaPr.X()) > Abs(PaPr.Y()))
+ {
+ Standard_Real xx = PaPr.X();
+ xx *= 0.5;
+ if (D1a.X())
+ {
+ da = -xx / D1a.X();
+ }
+ if (d2d.X())
+ {
+ dr = -xx / d2d.X();
+ }
+ }
+ else
+ {
+ Standard_Real yy = PaPr.Y();
+ yy *= 0.5;
+ if (D1a.Y())
+ {
+ da = -yy / D1a.Y();
+ }
+ if (d2d.Y())
+ {
+ dr = -yy / d2d.Y();
+ }
+ }
+ }
+ //-- Standard_Real da = -PaPr.Dot(D1a);
+ //-- Standard_Real dr = -PaPr.Dot(d2d);
+
+ if (da < -damax)
+ da = -damax;
+ else if (da > damax)
+ da = damax;
+ if (dr < -drmax)
+ dr = -drmax;
+ else if (dr > drmax)
+ dr = drmax;
+
+ if (Abs(da) < 1e-10 && Abs(dr) < 1e-10)
+ {
+ para = theta;
+ PSurf = alin->Value(para);
+ _theparameteronarc = theparameteronarc;
+ thepointonarc = alin->Value(para);
+ cpasok = Standard_False;
+ //-- printf("\nt:%d",nbiter);
+ return (Standard_True);
+ }
+ else
+ {
+ theta += da;
+ theparameteronarc += dr;
+ if (theparameteronarc > thearc->LastParameter())
+ {
+ theparameteronarc = thearc->LastParameter();
+ }
+ if (theparameteronarc < thearc->FirstParameter())
+ {
+ theparameteronarc = thearc->FirstParameter();
+ }
+ if (theta < u0alin)
+ {
+ theta = u0alin;
+ }
+ if (theta > u1alin - du)
+ {
+ theta = u1alin - du - du;
+ }
+ }
+ nbiter++;
+ } while (cpasok && nbiter < 20);
+ if (bestdist < distinit)
+ {
+ para = besttheta;
+ PSurf = alin->Value(para);
+ _theparameteronarc = bestpara;
+ thepointonarc = alin->Value(para);
+ //-- printf("\nT:%d",nbiter);
+ return (Standard_True);
+ }
+ //-- printf("\nF:%d",nbiter);
+ return (Standard_False);
+}
+
+//-- ======================================================================
+static void Recadre(const Handle(Adaptor3d_Surface)& myHS1,
+ const Handle(Adaptor3d_Surface)& myHS2,
+ Standard_Real& u1,
+ Standard_Real& v1,
+ Standard_Real& u2,
+ Standard_Real& v2)
+{
+ Standard_Real f, l, lmf, fpls2;
+ GeomAbs_SurfaceType typs1 = myHS1->GetType();
+ GeomAbs_SurfaceType typs2 = myHS2->GetType();
+
+ Standard_Boolean myHS1IsUPeriodic, myHS1IsVPeriodic;
+ switch (typs1)
+ {
+ case GeomAbs_Cylinder:
+ case GeomAbs_Cone:
+ case GeomAbs_Sphere:
+ {
+ myHS1IsUPeriodic = Standard_True;
+ myHS1IsVPeriodic = Standard_False;
+ break;
+ }
+ case GeomAbs_Torus:
+ {
+ myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True;
+ break;
+ }
+ default:
+ {
+ //-- Le cas de biparametrees periodiques est gere en amont
+ myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False;
+ break;
+ }
+ }
+
+ Standard_Boolean myHS2IsUPeriodic, myHS2IsVPeriodic;
+ switch (typs2)
+ {
+ case GeomAbs_Cylinder:
+ case GeomAbs_Cone:
+ case GeomAbs_Sphere:
+ {
+ myHS2IsUPeriodic = Standard_True;
+ myHS2IsVPeriodic = Standard_False;
+ break;
+ }
+ case GeomAbs_Torus:
+ {
+ myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True;
+ break;
+ }
+ default:
+ {
+ //-- Le cas de biparametrees periodiques est gere en amont
+ myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False;
+ break;
+ }
+ }
+ if (myHS1IsUPeriodic)
+ {
+ lmf = M_PI + M_PI; //-- myHS1->UPeriod();
+ f = myHS1->FirstUParameter();
+ l = myHS1->LastUParameter();
+ fpls2 = 0.5 * (f + l);
+ while ((u1 < f) && ((fpls2 - u1) > (u1 + lmf - fpls2)))
+ {
+ u1 += lmf;
+ }
+ while ((u1 > l) && ((u1 - fpls2) > (fpls2 - (u1 - lmf))))
+ {
+ u1 -= lmf;
+ }
+ }
+ if (myHS1IsVPeriodic)
+ {
+ lmf = M_PI + M_PI; //-- myHS1->VPeriod();
+ f = myHS1->FirstVParameter();
+ l = myHS1->LastVParameter();
+ fpls2 = 0.5 * (f + l);
+ while ((v1 < f) && ((fpls2 - v1) > (v1 + lmf - fpls2)))
+ {
+ v1 += lmf;
+ }
+ while ((v1 > l) && ((v1 - fpls2) > (fpls2 - (v1 - lmf))))
+ {
+ v1 -= lmf;
+ }
+ //-- while(v1 < f) { v1+=lmf; }
+ //-- while(v1 > l) { v1-=lmf; }
+ }
+ if (myHS2IsUPeriodic)
+ {
+ lmf = M_PI + M_PI; //-- myHS2->UPeriod();
+ f = myHS2->FirstUParameter();
+ l = myHS2->LastUParameter();
+ fpls2 = 0.5 * (f + l);
+ while ((u2 < f) && ((fpls2 - u2) > (u2 + lmf - fpls2)))
+ {
+ u2 += lmf;
+ }
+ while ((u2 > l) && ((u2 - fpls2) > (fpls2 - (u2 - lmf))))
+ {
+ u2 -= lmf;
+ }
+ //-- while(u2 < f) { u2+=lmf; }
+ //-- while(u2 > l) { u2-=lmf; }
+ }
+ if (myHS2IsVPeriodic)
+ {
+ lmf = M_PI + M_PI; //-- myHS2->VPeriod();
+ f = myHS2->FirstVParameter();
+ l = myHS2->LastVParameter();
+ fpls2 = 0.5 * (f + l);
+ while ((v2 < f) && ((fpls2 - v2) > (v2 + lmf - fpls2)))
+ {
+ v2 += lmf;
+ }
+ while ((v2 > l) && ((v2 - fpls2) > (fpls2 - (v2 - lmf))))
+ {
+ v2 -= lmf;
+ }
+ //-- while(v2 < f) { v2+=lmf; }
+ //-- while(v2 > l) { v2-=lmf; }
+ }
+}
+//=======================================================================
+//function : PutPointsOnLine
+//purpose :
+//=======================================================================
+void PutPointsOnLine(const Handle(Adaptor3d_Surface)& S1,
+ const Handle(Adaptor3d_Surface)& S2,
+ const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
+ const IntPatch_SequenceOfLine& slin,
+ const Standard_Boolean OnFirst,
+ const Handle(Adaptor3d_TopolTool)& Domain,
+ const IntSurf_Quadric& QuadSurf,
+ const IntSurf_Quadric& OtherQuad,
+ const Standard_Boolean multpoint,
+ const Standard_Real Tolarc)
+{
+ // Traitement des point (de listpnt) de depart. On les replace sur
+ // la ligne d intersection, en leur affectant la transition correcte sur
+ // cette ligne.
+ Standard_Integer nbpnt = listpnt.Length();
+ Standard_Integer nblin = slin.Length();
+
+ if (!slin.Length() || !nbpnt)
+ {
+ return;
+ }
+ //
+ Standard_Integer i, k;
+ Standard_Integer linenumber;
+ Standard_Real currentparameter, tolerance;
+ Standard_Real U1, V1, U2, V2;
+ Standard_Boolean goon;
+
+ gp_Pnt Psurf, ptbid;
+ gp_Vec Normale, Vtgint, Vtgrst;
+
+ gp_Vec d1u, d1v;
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+
+ IntSurf_Transition Transline, Transarc;
+
+ Handle(Adaptor2d_Curve2d) currentarc;
+ Handle(Adaptor3d_HVertex) vtx, vtxbis;
+
+ IntPatch_Point solpnt;
+ IntPatch_ThePathPointOfTheSOnBounds currentpointonrst;
+ IntPatch_IType TheType;
+
+ TColStd_Array1OfInteger UsedLine(1, nblin);
+ TColStd_Array1OfInteger Done(1, nbpnt);
+ for (i = 1; i <= nbpnt; i++)
+ Done(i) = 0; //-- Initialisation a la main
+
+ for (i = 1; i <= nbpnt; i++)
+ {
+ if (Done(i) != 1)
+ {
+ currentpointonrst = listpnt.Value(i);
+ Psurf = currentpointonrst.Value(); // Point dans l espace
+ tolerance = currentpointonrst.Tolerance();
+
+ // On recherche d abord si on a correspondance avec un "point multiple"
+ UsedLine.Init(0);
+
+ goon = Standard_True;
+ if (multpoint)
+ {
+#if 1
+ Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+ currentarc->D1(currentparameter, p2d, d2d);
+ QuadSurf.D1(p2d.X(), p2d.Y(), ptbid, d1u, d1v);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+#endif
+ goon = MultiplePoint(listpnt, Domain, QuadSurf, Normale, slin, Done, UsedLine, i, OnFirst, Tolarc);
+ }
+ if (goon)
+ {
+ Standard_Boolean linefound = Standard_False;
+
+ for (Standard_Integer indiceline = 1; indiceline <= slin.Length(); indiceline++)
+ {
+ if (UsedLine(indiceline) != 0)
+ continue;
+ linenumber = indiceline;
+
+ //-- Attention , les points peuvent etre deplaces
+ //-- il faut reprendre le point original
+ currentpointonrst = listpnt.Value(i);
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+ Psurf = currentpointonrst.Value(); // Point dans l espace
+ tolerance = currentpointonrst.Tolerance();
+ //--
+
+ // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 Begin
+ if (!currentpointonrst.IsNew())
+ {
+ Handle(Adaptor3d_HVertex) aVtx = currentpointonrst.Vertex();
+ Standard_Real aVtxTol = aVtx->Resolution(currentarc);
+ Standard_Real aTolAng = 0.01 * tolerance;
+
+ tolerance = Max(tolerance, aVtxTol);
+
+ gp_Vec aNorm1 = QuadSurf.Normale(Psurf);
+ gp_Vec aNorm2 = OtherQuad.Normale(Psurf);
+ //
+ if (aNorm1.Magnitude() > gp::Resolution() && aNorm2.Magnitude() > gp::Resolution())
+ {
+ if (aNorm1.IsParallel(aNorm2, aTolAng))
+ tolerance = Sqrt(tolerance);
+ } //
+ }
+ // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 End
+ gp_Pnt pointonarc;
+ Vtgint.SetCoord(0, 0, 0);
+ Standard_Real aVertTol = Tolarc;
+ TColStd_ListOfReal aLParams;
+ linefound = FindLine(Psurf,
+ slin,
+ tolerance,
+ aLParams,
+ Vtgint,
+ linenumber,
+ indiceline,
+ currentarc,
+ currentparameter,
+ pointonarc,
+ QuadSurf,
+ OtherQuad,
+ aVertTol);
+ if (linefound)
+ {
+#if 1
+ Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point
+ currentarc = currentpointonrst.Arc();
+ //-- currentparameter = currentpointonrst.Parameter();
+ currentarc->D1(currentparameter, p2d, d2d);
+ QuadSurf.D1(p2d.X(), p2d.Y(), ptbid, d1u, d1v);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+#endif
+
+ const Handle(IntPatch_Line)& lin = slin.Value(linenumber);
+ TheType = lin->ArcType();
+
+ if (!OnFirst)
+ { // on cherche la correspondance entre point sur domaine
+ // de la premiere surface et point sur domaine de la
+ // deuxieme surface
+
+ goon = PointOnSecondDom(listpnt, Domain, QuadSurf, Normale, Vtgint, lin, Done, i, aVertTol);
+ }
+
+ if (goon)
+ {
+ //-- Modification du 4 avril 97 tolerance->Tolarc
+ //-- on replace sur le vertex la tolerance d entree et
+ //-- non la tolerance qui a servi au FindLine
+ solpnt.SetValue(Psurf, aVertTol, Standard_False);
+
+ U1 = p2d.X();
+ V1 = p2d.Y();
+ OtherQuad.Parameters(Psurf, U2, V2);
+
+ if (OnFirst)
+ {
+ Recadre(S1, S2, U1, V1, U2, V2);
+ solpnt.SetParameters(U1, V1, U2, V2);
+ }
+ else
+ {
+ Recadre(S1, S2, U2, V2, U1, V1);
+ solpnt.SetParameters(U2, V2, U1, V1);
+ }
+
+ if (!currentpointonrst.IsNew())
+ {
+ vtx = currentpointonrst.Vertex();
+ solpnt.SetVertex(OnFirst, vtx);
+ }
+ else
+ {
+ //-- goon = Standard_False; ????
+ }
+
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+ solpnt.SetArc(OnFirst, currentarc, currentparameter, Transline, Transarc);
+
+ for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next())
+ {
+ solpnt.SetParameter(anItr.Value());
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(solpnt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(solpnt);
+ }
+ }
+
+ Done(i) = 1;
+
+ if (goon)
+ {
+ for (k = i + 1; k <= nbpnt; k++)
+ {
+ if (Done(k) != 1)
+ {
+ currentpointonrst = listpnt.Value(k);
+ if (!currentpointonrst.IsNew())
+ {
+ vtxbis = currentpointonrst.Vertex();
+ if (vtx.IsNull())
+ {
+ }
+ else if (Domain->Identical(vtx, vtxbis))
+ {
+ solpnt.SetVertex(OnFirst, vtxbis);
+ solpnt.SetTolerance(Tolarc);
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+
+ // currentarc->D1(currentparameter,ptbid,Vtgrst);
+ currentarc->D1(currentparameter, p2d, d2d);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+ solpnt.SetArc(OnFirst, currentarc, currentparameter, Transline, Transarc);
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(solpnt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(solpnt);
+ }
+ Done(k) = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Done(i) = 1; // il faudra tester si IsNew ou pas
+ // et traiter en consequence
+ }
+ }
+ }
+ }
+ }
+}
+
+Standard_Boolean MultiplePoint(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
+ const Handle(Adaptor3d_TopolTool)& Domain,
+ const IntSurf_Quadric& QuadSurf,
+ const gp_Vec& Normale,
+ const IntPatch_SequenceOfLine& slin,
+ TColStd_Array1OfInteger& Done,
+ TColStd_Array1OfInteger& UsedLine,
+ const Standard_Integer Index,
+ const Standard_Boolean OnFirst,
+ const Standard_Real theToler)
+{
+ // Traitement des points "multiples".
+
+ Standard_Integer k, ii, jj, nbvtx;
+ Standard_Integer nblin = slin.Length();
+ IntPatch_IType TheType;
+
+ IntSurf_Transition Transline, Transarc;
+
+ IntPatch_Point intpt;
+ Handle(Adaptor2d_Curve2d) currentarc;
+ Handle(Adaptor3d_HVertex) vtx, vtxbis;
+
+ Standard_Integer nbpnt = listpnt.Length();
+ IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index);
+ IntPatch_ThePathPointOfTheSOnBounds otherpt;
+ gp_Pnt Point = currentpointonrst.Value();
+ TColStd_Array1OfInteger localdone(1, nbpnt);
+ localdone.Init(0);
+ for (ii = 1; ii <= nbpnt; ii++)
+ {
+ localdone(ii) = Done(ii);
+ }
+
+ Standard_Real currentparameter;
+ Standard_Real Paraint;
+ gp_Vec Vtgint, Vtgrst;
+ gp_Pnt ptbid;
+
+ gp_Vec d1u, d1v;
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+
+ Standard_Boolean goon;
+
+ Standard_Boolean Retvalue = Standard_True;
+
+ for (ii = 1; ii <= nblin; ii++)
+ {
+ const Handle(IntPatch_Line)& slinValueii = slin.Value(ii);
+ TheType = slinValueii->ArcType();
+ if (TheType == IntPatch_Analytic)
+ {
+ nbvtx = Handle(IntPatch_ALine)::DownCast(slinValueii)->NbVertex();
+ }
+ else
+ {
+ nbvtx = Handle(IntPatch_GLine)::DownCast(slinValueii)->NbVertex();
+ }
+ jj = 1;
+ while (jj <= nbvtx)
+ {
+ if (TheType == IntPatch_Analytic)
+ {
+ intpt = Handle(IntPatch_ALine)::DownCast(slinValueii)->Vertex(jj);
+ }
+ else
+ {
+ intpt = Handle(IntPatch_GLine)::DownCast(slinValueii)->Vertex(jj);
+ }
+ if (intpt.IsMultiple() && ((OnFirst && !intpt.IsOnDomS1()) || (!OnFirst && !intpt.IsOnDomS2())))
+ {
+ if (Point.Distance(intpt.Value()) <= intpt.Tolerance())
+ {
+ Retvalue = Standard_False;
+ Standard_Boolean foo = SingleLine(Point, slinValueii, intpt.Tolerance(), Paraint, Vtgint);
+ if (!foo)
+ {
+ return Standard_False; // ne doit pas se produire
+ }
+
+ if (!currentpointonrst.IsNew())
+ {
+ goon = Standard_True;
+ vtx = currentpointonrst.Vertex();
+ intpt.SetVertex(OnFirst, vtx);
+ }
+ else
+ {
+ goon = Standard_False;
+ }
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+ currentarc->D1(currentparameter, p2d, d2d);
+ QuadSurf.D1(p2d.X(), p2d.Y(), ptbid, d1u, d1v);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+
+ //-- Si la normale est nulle (apex d un cone) On simule une transition UNKNOWN
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+
+ //-- Avant, on ne mettait pas ce point (17 nov 97)
+ //--printf("\n ImpImp_0 : Point(%g,%g,%g) intpt(%g,%g,%g) \n",
+ //-- Point.X(),Point.Y(),Point.Z(),intpt.Value().X(),intpt.Value().Y(),intpt.Value().Z());
+ intpt.SetValue(Point);
+
+ intpt.SetArc(OnFirst, currentarc, currentparameter, Transline, Transarc);
+ intpt.SetTolerance(theToler);
+
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(slinValueii)->Replace(jj, intpt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(slinValueii)->Replace(jj, intpt);
+ }
+ localdone(Index) = 1;
+ if (goon)
+ {
+ for (k = Index + 1; k <= nbpnt; k++)
+ {
+ if (Done(k) != 1)
+ {
+ otherpt = listpnt.Value(k);
+ if (!otherpt.IsNew())
+ {
+ vtxbis = otherpt.Vertex();
+ if (Domain->Identical(vtx, vtxbis))
+ {
+ intpt.SetVertex(OnFirst, vtxbis);
+ currentarc = otherpt.Arc();
+ currentparameter = otherpt.Parameter();
+
+ currentarc->D1(currentparameter, p2d, d2d);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+ intpt.SetArc(OnFirst, currentarc, currentparameter, Transline, Transarc);
+ intpt.SetTolerance(theToler);
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(slinValueii)->AddVertex(intpt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(slinValueii)->AddVertex(intpt);
+ }
+ UsedLine(ii) = 1;
+ Retvalue = Standard_True;
+ localdone(k) = 1;
+ }
+ }
+ }
+ }
+ }
+ //-- jj = nbvtx +1;
+ }
+ //-- else {
+ jj = jj + 1;
+ //-- }
+ }
+ else
+ {
+ jj = jj + 1;
+ }
+ }
+ }
+
+ for (ii = 1; ii <= nbpnt; ii++)
+ {
+ Done(ii) = localdone(ii);
+ }
+
+ return Retvalue;
+}
+
+Standard_Boolean PointOnSecondDom(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
+ const Handle(Adaptor3d_TopolTool)& Domain,
+ const IntSurf_Quadric& QuadSurf,
+ const gp_Vec& Normale,
+ const gp_Vec& Vtgint,
+ const Handle(IntPatch_Line)& lin,
+ TColStd_Array1OfInteger& Done,
+ const Standard_Integer Index,
+ const Standard_Real theToler)
+
+// Duplication des points sur domaine de l autre surface.
+// On sait que le vertex sous-jacent est PntRef
+
+{
+ Standard_Integer k, jj, nbvtx;
+ IntPatch_IType TheType;
+
+ IntSurf_Transition Transline, Transarc;
+ IntPatch_Point intpt;
+ Handle(Adaptor2d_Curve2d) currentarc;
+ Handle(Adaptor3d_HVertex) vtx, vtxbis;
+ gp_Pnt ptbid;
+ gp_Vec Vtgrst;
+
+ gp_Vec d1u, d1v;
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+
+ Standard_Integer nbpnt = listpnt.Length();
+ IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index);
+ Standard_Real currentparameter;
+
+ Standard_Boolean goon;
+ Standard_Boolean Retvalue = Standard_True;
+
+ TheType = lin->ArcType();
+ if (TheType == IntPatch_Analytic)
+ {
+ nbvtx = Handle(IntPatch_ALine)::DownCast(lin)->NbVertex();
+ }
+ else
+ {
+ nbvtx = Handle(IntPatch_GLine)::DownCast(lin)->NbVertex();
+ }
+ jj = 1;
+ while (jj <= nbvtx)
+ {
+ if (TheType == IntPatch_Analytic)
+ {
+ intpt = Handle(IntPatch_ALine)::DownCast(lin)->Vertex(jj);
+ }
+ else
+ {
+ intpt = Handle(IntPatch_GLine)::DownCast(lin)->Vertex(jj);
+ }
+ if (!intpt.IsOnDomS2())
+ {
+ if (currentpointonrst.Value().Distance(intpt.Value()) <= intpt.Tolerance())
+ {
+ Retvalue = Standard_False;
+ if (!currentpointonrst.IsNew())
+ {
+ goon = Standard_True;
+ vtx = currentpointonrst.Vertex();
+ intpt.SetVertex(Standard_False, vtx);
+ }
+ else
+ {
+ goon = Standard_False;
+ }
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+ currentarc->D1(currentparameter, p2d, d2d);
+ QuadSurf.D1(p2d.X(), p2d.Y(), ptbid, d1u, d1v);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+ intpt.SetArc(Standard_False, currentarc, currentparameter, Transline, Transarc);
+ intpt.SetTolerance(theToler);
+
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(lin)->Replace(jj, intpt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(lin)->Replace(jj, intpt);
+ }
+ Done(Index) = 1;
+
+ if (goon)
+ {
+ for (k = Index + 1; k <= nbpnt; k++)
+ {
+ if (Done(k) != 1)
+ {
+ currentpointonrst = listpnt.Value(k);
+ if (!currentpointonrst.IsNew())
+ {
+ vtxbis = currentpointonrst.Vertex();
+ if (Domain->Identical(vtx, vtxbis))
+ {
+ intpt.SetVertex(Standard_False, vtxbis);
+ currentarc = currentpointonrst.Arc();
+ currentparameter = currentpointonrst.Parameter();
+ currentarc->D1(currentparameter, p2d, d2d);
+ Vtgrst.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (Normale.SquareMagnitude() < 1e-16)
+ {
+ Transline.SetValue(Standard_True, IntSurf_Undecided);
+ Transarc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(Vtgint, Vtgrst, Normale, Transline, Transarc);
+ }
+ intpt.SetArc(Standard_False, currentarc, currentparameter, Transline, Transarc);
+ intpt.SetTolerance(theToler);
+ if (TheType == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(intpt);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(intpt);
+ }
+ Done(k) = 1;
+ }
+ }
+ }
+ }
+ }
+ //-- jj = nbvtx + 1;
+ jj++;
+ }
+ else
+ {
+ jj = jj + 1;
+ }
+ }
+ else
+ {
+ jj = jj + 1;
+ }
+ if (TheType == IntPatch_Analytic)
+ {
+ nbvtx = Handle(IntPatch_ALine)::DownCast(lin)->NbVertex();
+ }
+ else
+ {
+ nbvtx = Handle(IntPatch_GLine)::DownCast(lin)->NbVertex();
+ }
+ }
+ return Retvalue;
+}
+
+Standard_Boolean FindLine(gp_Pnt& Psurf,
+ const IntPatch_SequenceOfLine& slin,
+ const Standard_Real Tol,
+ TColStd_ListOfReal& theLParams,
+ gp_Vec& Vtgtint,
+ Standard_Integer& theLineIdx,
+ Standard_Integer OnlyThisLine,
+ const Handle(Adaptor2d_Curve2d)& thearc,
+ Standard_Real& theparameteronarc,
+ gp_Pnt& thepointonarc,
+ const IntSurf_Quadric& QuadSurf1,
+ const IntSurf_Quadric& QuadSurf2,
+ Standard_Real& theOutputToler)
+{
+ if ((QuadSurf1.Distance(Psurf) > Tol) || (QuadSurf2.Distance(Psurf) > Tol))
+ return Standard_False;
+
+ // Traitement du point de depart ayant pour representation Psurf
+ // dans l espace. On recherche la ligne d intersection contenant ce point.
+ // On a en sortie la ligne, et le parametre et sa tangente du point sur
+ // la ligne d intersection.
+ const Standard_Real aSqTol = Tol * Tol;
+ Standard_Real aSqDistMin = RealLast();
+ Standard_Real aSqDist, para;
+ Standard_Real lower, upper;
+ gp_Pnt pt;
+ Standard_Integer i;
+ IntPatch_IType typarc;
+
+ Standard_Real aParaInt = RealLast();
+ Standard_Integer nblin = slin.Length();
+ for (i = 1; i <= nblin; i++)
+ {
+ if (OnlyThisLine)
+ {
+ i = OnlyThisLine;
+ nblin = 0;
+ }
+ const Handle(IntPatch_Line)& lin = slin.Value(i);
+ typarc = lin->ArcType();
+ if (typarc == IntPatch_Analytic)
+ {
+ Standard_Boolean foo;
+ lower = Handle(IntPatch_ALine)::DownCast(lin)->FirstParameter(foo);
+ upper = Handle(IntPatch_ALine)::DownCast(lin)->LastParameter(foo);
+ }
+ else
+ {
+ if (Handle(IntPatch_GLine)::DownCast(lin)->HasFirstPoint())
+ {
+ lower = Handle(IntPatch_GLine)::DownCast(lin)->FirstPoint().ParameterOnLine();
+ }
+ else
+ {
+ lower = RealFirst();
+ }
+ if (Handle(IntPatch_GLine)::DownCast(lin)->HasLastPoint())
+ {
+ upper = Handle(IntPatch_GLine)::DownCast(lin)->LastPoint().ParameterOnLine();
+ }
+ else
+ {
+ upper = RealLast();
+ }
+ }
+
+ switch (typarc)
+ {
+ case IntPatch_Lin:
+ {
+ para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Line(), Psurf);
+ if (para <= upper && para >= lower)
+ {
+ pt = ElCLib::Value(para, Handle(IntPatch_GLine)::DownCast(lin)->Line());
+ aSqDist = Psurf.SquareDistance(pt);
+ if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
+ {
+ aSqDistMin = aSqDist;
+ aParaInt = para;
+ theLineIdx = i;
+ }
+ }
+ }
+ break;
+ case IntPatch_Circle:
+ {
+ para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Circle(), Psurf);
+ if ((para <= upper && para >= lower) || (para + 2. * M_PI <= upper && para + 2. * M_PI >= lower)
+ || (para - 2. * M_PI <= upper && para - 2. * M_PI >= lower))
+ {
+ pt = ElCLib::Value(para, Handle(IntPatch_GLine)::DownCast(lin)->Circle());
+ aSqDist = Psurf.SquareDistance(pt);
+ if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
+ {
+ aSqDistMin = aSqDist;
+ aParaInt = para;
+ theLineIdx = i;
+ }
+ }
+ }
+ break;
+ case IntPatch_Ellipse:
+ {
+ para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Ellipse(), Psurf);
+ if ((para <= upper && para >= lower) || (para + 2. * M_PI <= upper && para + 2. * M_PI >= lower)
+ || (para - 2. * M_PI <= upper && para - 2. * M_PI >= lower))
+ {
+ pt = ElCLib::Value(para, Handle(IntPatch_GLine)::DownCast(lin)->Ellipse());
+ aSqDist = Psurf.SquareDistance(pt);
+ if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
+ {
+ aSqDistMin = aSqDist;
+ aParaInt = para;
+ theLineIdx = i;
+ }
+ }
+ }
+ break;
+ case IntPatch_Parabola:
+ {
+#if 0
+ para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),Psurf);
+ if (para <= upper && para >= lower) {
+ pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Parabola());
+ dist = Psurf.Distance(pt);
+ if (dist< distmin) {
+ distmin = dist;
+ Paraint = para;
+ Range = i;
+ }
+ }
+#else
+ //-- Le calcul du parametre sur une parabole est mal fait ds ElCLib. Il ne tient pas compte
+ //-- de la meilleure facon de calculer (axe X ou axe Y). Bilan : Si la parabole est tres
+ //-- pointue (focal de l'ordre de 1e-2 et si le point est a un parametre grand, ca foire. )
+ //-- On ne peut pas modifier faciolement ds ElCLib car on ne passe pas la focale. ...
+ const gp_Parab& Parab = Handle(IntPatch_GLine)::DownCast(lin)->Parabola();
+ para = ElCLib::Parameter(Parab, Psurf);
+ if (para <= upper && para >= lower)
+ {
+ Standard_Integer amelioration = 0;
+ //-- cout<<"\n ****** \n";
+ do
+ {
+ Standard_Real parabis = para + 0.0000001;
+
+ pt = ElCLib::Value(para, Parab);
+ aSqDist = Psurf.SquareDistance(pt);
+
+ const gp_Pnt ptbis = ElCLib::Value(parabis, Parab);
+ const Standard_Real distbis = Psurf.Distance(ptbis);
+ const Standard_Real aDist = Sqrt(aSqDist);
+ const Standard_Real ddist = distbis - aDist;
+
+ //--cout<<" para: "<<para<<" dist:"<<dist<<" ddist:"<<ddist<<endl;
+
+ if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
+ {
+ aSqDistMin = aSqDist;
+ aParaInt = para;
+ theLineIdx = i;
+ }
+ if (aSqDist < Precision::SquarePConfusion())
+ {
+ amelioration = 100;
+ }
+
+ if (ddist > 1.0e-9 || ddist < -1.0e-9)
+ {
+ para = para - aDist * (parabis - para) / ddist;
+ }
+ else
+ {
+ amelioration = 100;
+ }
+ } while (++amelioration < 5);
+ }
+
+#endif
+ }
+ break;
+ case IntPatch_Hyperbola:
+ {
+ para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Hyperbola(), Psurf);
+ if (para <= upper && para >= lower)
+ {
+ pt = ElCLib::Value(para, Handle(IntPatch_GLine)::DownCast(lin)->Hyperbola());
+ aSqDist = Psurf.SquareDistance(pt);
+ if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
+ {
+ aSqDistMin = aSqDist;
+ aParaInt = para;
+ theLineIdx = i;
+ }
+ }
+ }
+ break;
+
+ case IntPatch_Analytic:
+ {
+ Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
+ TColStd_ListOfReal aLParams;
+ alin->FindParameter(Psurf, aLParams);
+ if (!aLParams.IsEmpty())
+ {
+ // All found distances are already in some internal tolerance
+ // set in alin->FindParameter(...) method.
+
+ aSqDist = RealLast();
+ for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next())
+ {
+ pt = alin->Value(anItr.Value());
+ const Standard_Real aSqD = Psurf.SquareDistance(pt);
+ if (aSqD < aSqDist)
+ {
+ aSqDist = aSqD;
+ }
+ }
+
+ if (aSqDist < aSqDistMin)
+ {
+ aSqDistMin = aSqDist;
+ theLParams = aLParams;
+ theLineIdx = i;
+ }
+ }
+ else
+ {
+ //-- le point n a pas ete trouve par bete projection.
+ //-- on essaie l intersection avec la restriction en 2d
+ Standard_Real theparamonarc = theparameteronarc;
+ //#ifdef OCCT_DEBUG
+ // Standard_Real anpara=para;
+ //#endif
+ gp_Pnt CopiePsurf = Psurf;
+ Standard_Boolean IntersectIsOk =
+ IntersectionWithAnArc(CopiePsurf, alin, para, thearc, theparamonarc, thepointonarc, QuadSurf1, lower, upper);
+ aSqDist = CopiePsurf.SquareDistance(Psurf);
+ if (IntersectIsOk)
+ {
+ if (aSqDist < aSqTol)
+ {
+ theparameteronarc = theparamonarc;
+ Psurf = thepointonarc;
+ aSqDistMin = aSqDist;
+ theLParams.Append(para);
+ theLineIdx = i;
+ }
+ }
+ }
+ }
+ break;
+
+ case IntPatch_Walking: // impossible . c est pour eviter les warnings
+ {
+ }
+ case IntPatch_Restriction: // impossible . c est pour eviter les warnings
+ {
+ }
+ }
+ }
+
+ if (aSqDistMin == RealLast())
+ return Standard_False;
+
+ theOutputToler = Max(theOutputToler, Sqrt(aSqDistMin));
+
+ typarc = slin.Value(theLineIdx)->ArcType();
+
+ // Computation of tangent vector
+ switch (typarc)
+ {
+ case IntPatch_Lin:
+ theLParams.Append(aParaInt);
+ Vtgtint = (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Line().Direction();
+ break;
+ case IntPatch_Circle:
+ theLParams.Append(aParaInt);
+ Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Circle(), 1);
+ break;
+ case IntPatch_Ellipse:
+ theLParams.Append(aParaInt);
+ Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Ellipse(), 1);
+ break;
+ case IntPatch_Parabola:
+ theLParams.Append(aParaInt);
+ Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Parabola(), 1);
+ break;
+ case IntPatch_Hyperbola:
+ theLParams.Append(aParaInt);
+ Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Hyperbola(), 1);
+ break;
+
+ case IntPatch_Analytic:
+ {
+ if (!Handle(IntPatch_ALine)::DownCast(slin(theLineIdx))->D1(theLParams.Last(), pt, Vtgtint))
+ {
+ //Previously (before the fix #29807) this code tried to process case
+ //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
+ //computed Vtgtint input argument value. Currently, any singularities
+ //must be processed by high-level algorithms (IntPatch_SpecialPoints class).
+ //Therefore this code has been deleted as deprecated.
+
+ Vtgtint.SetCoord(0.0, 0.0, 0.0);
+ }
+ }
+ break;
+ case IntPatch_Walking: // impossible . c est pour eviter les warnings
+ {
+ }
+ case IntPatch_Restriction: // impossible . c est pour eviter les warnings
+ {
+ }
+ }
+ return Standard_True;
+}
+
+//=======================================================================
+//function : SingleLine
+//purpose : Traitement du point de depart ayant pour representation Psurf
+// dans l espace. On le replace sur la ligne d intersection; On a en sortie
+// son parametre et sa tangente sur la ligne d intersection.
+// La fonction renvoie False si le point projete est a une distance
+// superieure a Tol du point a projeter.
+//=======================================================================
+Standard_Boolean SingleLine(const gp_Pnt& Psurf,
+ const Handle(IntPatch_Line)& lin,
+ const Standard_Real Tol,
+ Standard_Real& Paraint,
+ gp_Vec& Vtgtint)
+{
+ IntPatch_IType typarc = lin->ArcType();
+
+ Standard_Real parproj = 0.;
+ gp_Vec tgint;
+ gp_Pnt ptproj;
+ Standard_Boolean retvalue;
+
+ switch (typarc)
+ {
+ case IntPatch_Lin:
+ parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Line(), Psurf);
+ ElCLib::D1(parproj, Handle(IntPatch_GLine)::DownCast(lin)->Line(), ptproj, tgint);
+ break;
+ case IntPatch_Circle:
+ parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Circle(), Psurf);
+ ElCLib::D1(parproj, Handle(IntPatch_GLine)::DownCast(lin)->Circle(), ptproj, tgint);
+ break;
+ case IntPatch_Ellipse:
+ parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Ellipse(), Psurf);
+ ElCLib::D1(parproj, Handle(IntPatch_GLine)::DownCast(lin)->Ellipse(), ptproj, tgint);
+ break;
+ case IntPatch_Parabola:
+ parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Parabola(), Psurf);
+ ElCLib::D1(parproj, Handle(IntPatch_GLine)::DownCast(lin)->Parabola(), ptproj, tgint);
+ break;
+ case IntPatch_Hyperbola:
+ parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast(lin)->Hyperbola(), Psurf);
+ ElCLib::D1(parproj, Handle(IntPatch_GLine)::DownCast(lin)->Hyperbola(), ptproj, tgint);
+ break;
+ case IntPatch_Analytic:
+ {
+ Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
+ TColStd_ListOfReal aLParams;
+ alin->FindParameter(Psurf, aLParams);
+ if (!aLParams.IsEmpty())
+ {
+ ptproj = Psurf;
+ parproj = aLParams.Last();
+ gp_Pnt aPtemp;
+ if (!alin->D1(parproj, aPtemp, tgint))
+ {
+ //Previously (before the fix #29807) this code tried to process case
+ //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
+ //computed Vtgtint input argument value. Currently, any singularities
+ //must be processed by high-level algorithms (IntPatch_SpecialPoints class).
+ //Therefore this code has been deleted as deprecated.
+
+ tgint.SetCoord(0.0, 0.0, 0.0);
+ }
+ }
+ else
+ {
+ //-- cout << "---- Pb sur ligne analytique dans SingleLine" << endl;
+ //-- cout << " Find Parameter"<<endl;
+ return Standard_False;
+ }
+ }
+ break;
+ case IntPatch_Walking: // impossible . c est pour eviter les warnings
+ {
+ }
+ case IntPatch_Restriction: // impossible . c est pour eviter les warnings
+ {
+ }
+ }
+
+ if (Psurf.Distance(ptproj) <= Tol)
+ {
+ Paraint = parproj;
+ Vtgtint = tgint;
+ retvalue = Standard_True;
+ }
+ else
+ {
+ retvalue = Standard_False;
+ }
+ return retvalue;
+}
+
+void ProcessSegments(const IntPatch_SequenceOfSegmentOfTheSOnBounds& listedg,
+ IntPatch_SequenceOfLine& slin,
+ const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Boolean OnFirst,
+ const Standard_Real TolArc)
+{
+ Standard_Integer i, j, k;
+ Standard_Integer nbedg = listedg.Length();
+ Standard_Integer Nblines, Nbpts;
+
+ Handle(Adaptor2d_Curve2d) arcRef;
+ IntPatch_Point ptvtx, newptvtx;
+
+ Handle(IntPatch_RLine) rline; //-- On fait rline = new ... par la suite
+
+ IntPatch_TheSegmentOfTheSOnBounds thesegsol;
+ IntPatch_ThePathPointOfTheSOnBounds PStartf, PStartl;
+ Standard_Boolean dofirst, dolast, procf, procl;
+
+ Standard_Real paramf = 0., paraml = 0., U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
+
+ IntPatch_IType typ;
+ IntSurf_TypeTrans trans1, trans2;
+ IntSurf_Transition TRest, TArc;
+ gp_Vec tgline, norm1, norm2, tgarc;
+ gp_Pnt valpt;
+
+ gp_Vec d1u, d1v;
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+
+ for (i = 1; i <= nbedg; i++)
+ {
+ Standard_Boolean EdgeDegenere = Standard_False;
+ thesegsol = listedg.Value(i);
+ arcRef = thesegsol.Curve();
+
+ rline = new IntPatch_RLine(Standard_False);
+ if (OnFirst)
+ {
+ rline->SetArcOnS1(arcRef);
+ }
+ else
+ {
+ rline->SetArcOnS2(arcRef);
+ }
+
+ // Traitement des points debut/fin du segment solution.
+
+ dofirst = Standard_False;
+ dolast = Standard_False;
+ procf = Standard_False;
+ procl = Standard_False;
+
+ if (thesegsol.HasFirstPoint())
+ {
+ dofirst = Standard_True;
+ PStartf = thesegsol.FirstPoint();
+ paramf = PStartf.Parameter();
+ }
+ if (thesegsol.HasLastPoint())
+ {
+ dolast = Standard_True;
+ PStartl = thesegsol.LastPoint();
+ paraml = PStartl.Parameter();
+ }
+
+ if (dofirst && dolast)
+ { // determination de la transition de la ligne
+ arcRef->D1(0.5 * (paramf + paraml), p2d, d2d);
+ if (OnFirst)
+ {
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ else
+ {
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ tgline.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+
+ if (d1u.Magnitude() < 1e-7)
+ { //-- edge degenere ?
+ EdgeDegenere = Standard_True;
+ for (Standard_Integer edg = 0; edg <= 10; edg++)
+ {
+ arcRef->D1(paramf + (paraml - paramf) * edg * 0.1, p2d, d2d);
+ if (OnFirst)
+ {
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ else
+ {
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+
+ if (d1u.Magnitude() > 1e-7)
+ {
+ EdgeDegenere = Standard_False;
+ }
+ }
+ rline = new IntPatch_RLine(Standard_False);
+ if (OnFirst)
+ {
+ rline->SetArcOnS1(arcRef);
+ }
+ else
+ {
+ rline->SetArcOnS2(arcRef);
+ }
+ }
+ else
+ {
+ norm2 = Quad2.Normale(valpt);
+ norm1 = Quad1.Normale(valpt);
+
+ if (tgline.DotCross(norm2, norm1) > 0.000000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (tgline.DotCross(norm2, norm1) < -0.000000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ rline = new IntPatch_RLine(Standard_False, trans1, trans2);
+ if (OnFirst)
+ {
+ rline->SetArcOnS1(arcRef);
+ }
+ else
+ {
+ rline->SetArcOnS2(arcRef);
+ }
+ }
+ }
+ else
+ {
+ rline = new IntPatch_RLine(Standard_False);
+ if (OnFirst)
+ {
+ rline->SetArcOnS1(arcRef);
+ }
+ else
+ {
+ rline->SetArcOnS2(arcRef);
+ }
+ }
+
+ if (dofirst || dolast)
+ {
+ Nblines = slin.Length();
+ for (j = 1; j <= Nblines; j++)
+ {
+ const Handle(IntPatch_Line)& slinj = slin(j);
+ typ = slinj->ArcType();
+ if (typ == IntPatch_Analytic)
+ {
+ Nbpts = Handle(IntPatch_ALine)::DownCast(slinj)->NbVertex();
+ }
+ else if (typ == IntPatch_Restriction)
+ {
+ Nbpts = Handle(IntPatch_RLine)::DownCast(slinj)->NbVertex();
+ }
+ else
+ {
+ Nbpts = Handle(IntPatch_GLine)::DownCast(slinj)->NbVertex();
+ }
+ for (k = 1; k <= Nbpts; k++)
+ {
+ if (typ == IntPatch_Analytic)
+ {
+ ptvtx = Handle(IntPatch_ALine)::DownCast(slinj)->Vertex(k);
+ }
+ else if (typ == IntPatch_Restriction)
+ {
+ ptvtx = Handle(IntPatch_RLine)::DownCast(slinj)->Vertex(k);
+ }
+ else
+ {
+ ptvtx = Handle(IntPatch_GLine)::DownCast(slinj)->Vertex(k);
+ }
+
+ if (EdgeDegenere == Standard_False && dofirst)
+ {
+ if (ptvtx.Value().Distance(PStartf.Value()) <= TolArc)
+ {
+ ptvtx.SetMultiple(Standard_True);
+ ptvtx.SetTolerance(TolArc);
+ if (typ == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+ else if (typ == IntPatch_Restriction)
+ {
+ Handle(IntPatch_RLine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+ newptvtx = ptvtx;
+ newptvtx.SetParameter(paramf);
+ //Recalcul des transitions si point sur restriction
+
+ arcRef->D1(paramf, p2d, d2d);
+ if (OnFirst)
+ {
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ else
+ {
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ tgline.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (ptvtx.IsOnDomS1())
+ {
+ const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS1();
+ thearc->D1(ptvtx.ParameterOnArc1(), p2d, d2d);
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm1 = d1u.Crossed(d1v);
+ if (norm1.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgline, tgarc, norm1, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_True, thearc, ptvtx.ParameterOnArc1(), TRest, TArc);
+ }
+ if (ptvtx.IsOnDomS2())
+ {
+ const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS2();
+ thearc->D1(ptvtx.ParameterOnArc2(), p2d, d2d);
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm2 = d1u.Crossed(d1v);
+ if (norm2.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgline, tgarc, norm2, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_False, thearc, ptvtx.ParameterOnArc2(), TRest, TArc);
+ }
+
+ rline->AddVertex(newptvtx);
+ if (!procf)
+ {
+ procf = Standard_True;
+ rline->SetFirstPoint(rline->NbVertex());
+ }
+ }
+ }
+ if (EdgeDegenere == Standard_False && dolast)
+ {
+ if (ptvtx.Value().Distance(PStartl.Value()) <= TolArc)
+ {
+ ptvtx.SetMultiple(Standard_True);
+ ptvtx.SetTolerance(TolArc);
+ if (typ == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+ else if (typ == IntPatch_Restriction)
+ {
+ Handle(IntPatch_RLine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(slinj)->Replace(k, ptvtx);
+ }
+
+ newptvtx = ptvtx;
+ newptvtx.SetParameter(paraml);
+ //Recalcul des transitions si point sur restriction
+
+ arcRef->D1(paraml, p2d, d2d);
+ if (OnFirst)
+ {
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ else
+ {
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ tgline.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ if (ptvtx.IsOnDomS1())
+ {
+ const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS1();
+ thearc->D1(ptvtx.ParameterOnArc1(), p2d, d2d);
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm1 = d1u.Crossed(d1v);
+ if (norm1.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgline, tgarc, norm1, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_True, thearc, ptvtx.ParameterOnArc1(), TRest, TArc);
+ }
+ if (ptvtx.IsOnDomS2())
+ {
+ const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS2();
+ thearc->D1(ptvtx.ParameterOnArc2(), p2d, d2d);
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm2 = d1u.Crossed(d1v);
+ if (norm2.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgline, tgarc, norm2, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_False, thearc, ptvtx.ParameterOnArc2(), TRest, TArc);
+ }
+
+ rline->AddVertex(newptvtx);
+ if (!procl)
+ {
+ procl = Standard_True;
+ rline->SetLastPoint(rline->NbVertex());
+ }
+ }
+ }
+ }
+ // Si on a traite le pt debut et/ou fin, on ne doit pas recommencer si
+ // il (ils) correspond(ent) a un point multiple.
+
+ if (procf)
+ {
+ dofirst = Standard_False;
+ }
+ if (procl)
+ {
+ dolast = Standard_False;
+ }
+ }
+ }
+ // Si on n a pas trouve le point debut et./ou fin sur une des lignes
+ // d intersection, il faut quand-meme le placer sur la restriction solution
+
+ if (dofirst)
+ {
+ ptvtx.SetValue(PStartf.Value(), PStartf.Tolerance(), Standard_False);
+ Quad1.Parameters(PStartf.Value(), U1, V1);
+ Quad2.Parameters(PStartf.Value(), U2, V2);
+ ptvtx.SetParameters(U1, V1, U2, V2);
+ ptvtx.SetParameter(paramf);
+ if (!PStartf.IsNew())
+ {
+ IntSurf_Transition Transline;
+ IntSurf_Transition Transarc;
+ ptvtx.SetVertex(OnFirst, PStartf.Vertex());
+ ptvtx.SetArc(OnFirst, PStartf.Arc(), PStartf.Parameter(), Transline, Transarc);
+ }
+
+ rline->AddVertex(ptvtx);
+ rline->SetFirstPoint(rline->NbVertex());
+ }
+ if (dolast)
+ {
+ ptvtx.SetValue(PStartl.Value(), PStartl.Tolerance(), Standard_False);
+ Quad1.Parameters(PStartl.Value(), U1, V1);
+ Quad2.Parameters(PStartl.Value(), U2, V2);
+ ptvtx.SetParameters(U1, V1, U2, V2);
+ ptvtx.SetParameter(paraml);
+ if (!PStartl.IsNew())
+ {
+ IntSurf_Transition Transline;
+ IntSurf_Transition Transarc;
+
+ ptvtx.SetVertex(OnFirst, PStartl.Vertex());
+ ptvtx.SetArc(OnFirst, PStartl.Arc(), PStartl.Parameter(), Transline, Transarc);
+ }
+
+ rline->AddVertex(ptvtx);
+ rline->SetLastPoint(rline->NbVertex());
+ }
+ slin.Append(rline);
+ }
+}
+
+inline const gp_Pnt& PointValue(const Handle(IntPatch_RLine) theRLine, const Standard_Integer theIndex)
+{
+ return theRLine->Point(theIndex).Value();
+}
+
+inline const gp_Pnt& VertexValue(const Handle(IntPatch_RLine) theRLine, const Standard_Integer theIndex)
+{
+ return theRLine->Vertex(theIndex).Value();
+}
+
+static Standard_Real SquareDistance(const Handle(IntPatch_GLine)& theGLine, const gp_Pnt& theP, Extrema_ExtPC& theExtr)
+{
+ Standard_Real aSQDist = RealLast();
+ switch (theGLine->ArcType())
+ {
+ case IntPatch_Lin: aSQDist = theGLine->Line().SquareDistance(theP); break;
+ case IntPatch_Circle: aSQDist = theGLine->Circle().SquareDistance(theP); break;
+ default:
+ theExtr.Perform(theP);
+ if (!theExtr.IsDone() || !theExtr.NbExt())
+ {
+ //Lines are not overlapped
+ return aSQDist;
+ }
+
+ aSQDist = theExtr.SquareDistance(1);
+ const Standard_Integer aNbExtr = theExtr.NbExt();
+ for (Standard_Integer i = 2; i <= aNbExtr; i++)
+ {
+ const Standard_Real aSQD = theExtr.SquareDistance(i);
+ if (aSQD < aSQDist)
+ {
+ aSQDist = aSQD;
+ }
+ }
+ }
+
+ return aSQDist;
+}
+
+static Standard_Boolean IsRLineGood(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Handle(IntPatch_GLine) theGLine,
+ const Handle(IntPatch_RLine) theRLine,
+ const Standard_Real theTol)
+{
+ const Standard_Real aSQTol = theTol * theTol;
+ const IntPatch_IType aGType = theGLine->ArcType();
+ Standard_Integer aNbPntsM1 = 0;
+
+ const gp_Pnt& (*Value)(const Handle(IntPatch_RLine), const Standard_Integer);
+
+ if (theRLine->HasPolygon())
+ {
+ aNbPntsM1 = theRLine->NbPnts() - 1;
+ Value = PointValue;
+ }
+ else
+ {
+ aNbPntsM1 = theRLine->NbVertex() - 1;
+ Value = VertexValue;
+ }
+
+ if (aNbPntsM1 < 1)
+ return Standard_False;
+
+ Extrema_ExtPC anExtr;
+ GeomAdaptor_Curve anAC;
+ Handle(Geom_Curve) aCurv;
+
+ if (aGType == IntPatch_Ellipse)
+ aCurv = new Geom_Ellipse(theGLine->Ellipse());
+ else if (aGType == IntPatch_Parabola)
+ aCurv = new Geom_Parabola(theGLine->Parabola());
+ else if (aGType == IntPatch_Hyperbola)
+ aCurv = new Geom_Hyperbola(theGLine->Hyperbola());
+
+ if (!aCurv.IsNull())
+ {
+ const Standard_Real anUinf = aCurv->FirstParameter(), anUsup = aCurv->LastParameter();
+ anAC.Load(aCurv, anUinf, anUsup);
+ anExtr.Initialize(anAC, anUinf, anUsup);
+ }
+
+ if (aNbPntsM1 == 1)
+ {
+ gp_Pnt aP1(Value(theRLine, 1)), aP2(Value(theRLine, 2));
+
+ if (aP1.SquareDistance(aP2) < aSQTol)
+ {
+ //RLine is degenerated
+ return Standard_False;
+ }
+
+ gp_Pnt aPMid;
+ if (theRLine->IsArcOnS1())
+ {
+ const Handle(Adaptor2d_Curve2d)& anAC2d = theRLine->ArcOnS1();
+ const Standard_Real aParF = anAC2d->FirstParameter(), aParL = anAC2d->LastParameter();
+ gp_Pnt2d aP2d(anAC2d->Value(0.5 * (aParF + aParL)));
+ aPMid = Quad1.Value(aP2d.X(), aP2d.Y());
+ }
+ else
+ {
+ const Handle(Adaptor2d_Curve2d)& anAC2d = theRLine->ArcOnS2();
+ const Standard_Real aParF = anAC2d->FirstParameter(), aParL = anAC2d->LastParameter();
+ gp_Pnt2d aP2d(anAC2d->Value(0.5 * (aParF + aParL)));
+ aPMid = Quad2.Value(aP2d.X(), aP2d.Y());
+ }
+
+ const Standard_Real aSQDist = SquareDistance(theGLine, aPMid, anExtr);
+ return (aSQDist > aSQTol);
+ }
+
+ for (Standard_Integer i = 2; i <= aNbPntsM1; i++)
+ {
+ const gp_Pnt aP(Value(theRLine, i));
+ const Standard_Real aSQDist = SquareDistance(theGLine, aP, anExtr);
+
+ if (aSQDist > aSQTol)
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+void ProcessRLine(IntPatch_SequenceOfLine& slin,
+ // const Handle(Adaptor3d_Surface)& Surf1,
+ // const Handle(Adaptor3d_Surface)& Surf2,
+ const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real _TolArc,
+ const Standard_Boolean theIsReqToKeepRLine)
+{
+ // On cherche a placer sur les restrictions solutions les points "multiples"
+ // des autres lignes d intersection
+ // Pas forcemment le plus efficace : on rique de projeter plusieurs fois
+ // le meme point sur la meme restriction...
+
+ Standard_Real TolArc = 100.0 * _TolArc;
+ if (TolArc > 0.1)
+ TolArc = 0.1;
+
+ Standard_Integer i, j, k;
+ Standard_Integer Nblin, Nbvtx, Nbpt;
+
+ Standard_Boolean OnFirst = Standard_False, project = Standard_False, keeppoint = Standard_False;
+
+ Handle(Adaptor2d_Curve2d) arcref;
+ Standard_Real paramproj, paramf, paraml;
+
+ TColgp_SequenceOfPnt seq_Pnt3d;
+ TColStd_SequenceOfReal seq_Real;
+
+ gp_Pnt ptproj, toproj, valpt;
+
+ gp_Pnt2d p2d;
+ gp_Vec2d d2d;
+ gp_Vec d1u, d1v, tgrest, tgarc, norm;
+ IntSurf_Transition TRest, TArc;
+#ifndef OCCT_DEBUG
+ Standard_Real U = 0., V = 0.;
+#else
+ Standard_Real U, V;
+#endif
+ IntPatch_Point Ptvtx, newptvtx;
+
+ IntPatch_IType typ1, typ2;
+
+ Nblin = slin.Length();
+ for (i = 1; i <= Nblin; i++)
+ {
+ const Handle(IntPatch_Line)& slini = slin(i);
+ typ1 = slini->ArcType();
+
+ Standard_Boolean HasToDeleteRLine = Standard_False;
+ if (typ1 == IntPatch_Restriction)
+ {
+ seq_Pnt3d.Clear();
+ seq_Real.Clear();
+
+ for (j = 1; j <= Nblin; j++)
+ {
+ const Handle(IntPatch_Line)& slinj = slin(j);
+ Nbpt = seq_Pnt3d.Length(); // important que ce soit ici
+ typ2 = slinj->ArcType();
+ if (typ2 != IntPatch_Restriction)
+ {
+ //-- arcref = Handle(IntPatch_RLine)::DownCast (slini)->Arc();
+ //-- OnFirst = Handle(IntPatch_RLine)::DownCast (slini)->IsOnFirstSurface();
+
+ //-- DES CHOSES A FAIRE ICI
+ if (Handle(IntPatch_RLine)::DownCast(slini)->IsArcOnS1())
+ {
+ OnFirst = Standard_True;
+ arcref = Handle(IntPatch_RLine)::DownCast(slini)->ArcOnS1();
+ }
+ else if (Handle(IntPatch_RLine)::DownCast(slini)->IsArcOnS2())
+ {
+ arcref = Handle(IntPatch_RLine)::DownCast(slini)->ArcOnS2();
+ OnFirst = Standard_False;
+ }
+ if (Handle(IntPatch_RLine)::DownCast(slini)->HasFirstPoint())
+ {
+ paramf = Handle(IntPatch_RLine)::DownCast(slini)->FirstPoint().ParameterOnLine();
+ }
+ else
+ {
+ // cout << "Pas de param debut sur rst solution" << endl;
+ paramf = RealFirst();
+ }
+ if (Handle(IntPatch_RLine)::DownCast(slini)->HasLastPoint())
+ {
+ paraml = Handle(IntPatch_RLine)::DownCast(slini)->LastPoint().ParameterOnLine();
+ }
+ else
+ {
+ // cout << "Pas de param debut sur rst solution" << endl;
+ paraml = RealLast();
+ }
+
+ if (typ2 == IntPatch_Analytic)
+ {
+ Nbvtx = Handle(IntPatch_ALine)::DownCast(slinj)->NbVertex();
+ }
+ else
+ {
+ Nbvtx = Handle(IntPatch_GLine)::DownCast(slinj)->NbVertex();
+ }
+
+ Standard_Boolean EdgeDegenere = Standard_True;
+ for (Standard_Integer edg = 0; EdgeDegenere && edg <= 10; edg++)
+ {
+ arcref->D1(paramf + (paraml - paramf) * edg * 0.1, p2d, d2d);
+ if (OnFirst)
+ {
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ else
+ {
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ }
+ if (d1u.Magnitude() > 1e-7)
+ {
+ EdgeDegenere = Standard_False;
+ }
+ }
+
+ for (k = 1; EdgeDegenere == Standard_False && k <= Nbvtx; k++)
+ {
+ if (typ2 == IntPatch_Analytic)
+ {
+ Ptvtx = Handle(IntPatch_ALine)::DownCast(slinj)->Vertex(k);
+ }
+ else
+ {
+ Ptvtx = Handle(IntPatch_GLine)::DownCast(slinj)->Vertex(k);
+ }
+ if ((OnFirst && !Ptvtx.IsOnDomS1()) || (!OnFirst && !Ptvtx.IsOnDomS2()))
+ {
+ // Si OnFirst && OnDomS1, c est qu on est a une extremite
+ // ca doit etre traite par Process Segment...
+ project = Standard_True;
+ keeppoint = Standard_False;
+ toproj = Ptvtx.Value();
+
+ Standard_Integer jj;
+ for (jj = 1; jj <= Nbpt; jj++)
+ {
+ //for (Standard_Integer jj = 1; jj <= Nbpt; jj++) {
+ if (toproj.Distance(seq_Pnt3d(jj)) < _TolArc)
+ {
+ project = Standard_False;
+ break;
+ }
+ }
+ if (project)
+ { //-- il faut projeter pour trouver le point sur la rline.
+ if (OnFirst)
+ {
+ Ptvtx.ParametersOnS1(U, V);
+ }
+ else
+ {
+ Ptvtx.ParametersOnS2(U, V);
+ }
+
+ project = IntPatch_HInterTool::Project(arcref, gp_Pnt2d(U, V), paramproj, p2d);
+
+ if (project)
+ {
+ if (OnFirst)
+ {
+ ptproj = Quad1.Value(p2d.X(), p2d.Y());
+ }
+ else
+ {
+ ptproj = Quad2.Value(p2d.X(), p2d.Y());
+ }
+ if ((toproj.Distance(ptproj) <= 100 * TolArc) && (paramproj >= paramf) && (paramproj <= paraml))
+ {
+ newptvtx = Ptvtx;
+ newptvtx.SetParameter(paramproj);
+ keeppoint = Standard_True;
+ seq_Pnt3d.Append(toproj);
+ seq_Real.Append(paramproj);
+
+ //-- verifier que si la restriction arcref est trouvee, elle porte ce vertex
+ for (int ri = 1; ri <= Nblin; ri++)
+ {
+ const Handle(IntPatch_Line)& slinri = slin(ri);
+ if (slinri->ArcType() == IntPatch_Restriction)
+ {
+ if (OnFirst && Handle(IntPatch_RLine)::DownCast(slinri)->IsArcOnS1())
+ {
+ if (arcref == Handle(IntPatch_RLine)::DownCast(slinri)->ArcOnS1())
+ {
+ Handle(IntPatch_RLine)::DownCast(slinri)->AddVertex(newptvtx);
+ //printf("\n ImpImpIntersection_0.gxx CAS1 \n");
+ }
+ }
+ else if (OnFirst == Standard_False && Handle(IntPatch_RLine)::DownCast(slinri)->IsArcOnS2())
+ {
+ if (arcref == Handle(IntPatch_RLine)::DownCast(slinri)->ArcOnS2())
+ {
+ Handle(IntPatch_RLine)::DownCast(slinri)->AddVertex(newptvtx);
+ //printf("\n ImpImpIntersection_0.gxx CAS2 \n");
+ }
+ }
+ }
+ }
+ // -- --------------------------------------------------
+ }
+ }
+ }
+ else
+ {
+ keeppoint = Standard_True;
+ newptvtx = Ptvtx;
+ newptvtx.SetParameter(seq_Real(jj));
+ }
+ if (keeppoint)
+ {
+ Ptvtx.SetMultiple(Standard_True);
+ Ptvtx.SetTolerance(_TolArc);
+ newptvtx.SetMultiple(Standard_True);
+
+ if (typ2 == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)::DownCast(slinj)->Replace(k, Ptvtx);
+ }
+ else
+ {
+ Handle(IntPatch_GLine)::DownCast(slinj)->Replace(k, Ptvtx);
+ }
+
+ if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2())
+ {
+ arcref->D1(newptvtx.ParameterOnLine(), p2d, d2d);
+
+ if (OnFirst)
+ { // donc OnDomS2
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgrest.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+
+ const Handle(Adaptor2d_Curve2d)& thearc = Ptvtx.ArcOnS2();
+ thearc->D1(Ptvtx.ParameterOnArc2(), p2d, d2d);
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm = d1u.Crossed(d1v); //Quad2.Normale(valpt);
+ if (norm.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgrest, tgarc, norm, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_False, thearc, Ptvtx.ParameterOnArc2(), TRest, TArc);
+ }
+ else
+ { // donc OnDomS1
+ Quad2.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgrest.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+
+ const Handle(Adaptor2d_Curve2d)& thearc = Ptvtx.ArcOnS1();
+ thearc->D1(Ptvtx.ParameterOnArc1(), p2d, d2d);
+ Quad1.D1(p2d.X(), p2d.Y(), valpt, d1u, d1v);
+ tgarc.SetLinearForm(d2d.X(), d1u, d2d.Y(), d1v);
+ norm = d1u.Crossed(d1v); //Quad1.Normale(valpt);
+ if (norm.SquareMagnitude() < 1e-16)
+ {
+ TRest.SetValue(Standard_True, IntSurf_Undecided);
+ TArc.SetValue(Standard_True, IntSurf_Undecided);
+ }
+ else
+ {
+ IntSurf::MakeTransition(tgrest, tgarc, norm, TRest, TArc);
+ }
+ newptvtx.SetArc(Standard_True, thearc, Ptvtx.ParameterOnArc1(), TRest, TArc);
+ }
+ } //-- if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2())
+
+ Handle(IntPatch_RLine)::DownCast(slini)->AddVertex(newptvtx);
+
+ } //-- if (keeppoint)
+ } //-- if ((OnFirst && !Ptvtx.IsOnDomS1())||(!OnFirst && !Ptvtx.IsOnDomS2()))
+ } //-- boucle sur les vertex
+
+ if (!theIsReqToKeepRLine)
+ {
+ Handle(IntPatch_GLine) aGL = Handle(IntPatch_GLine)::DownCast(slinj);
+
+ if (!aGL.IsNull())
+ {
+ HasToDeleteRLine = !IsRLineGood(Quad1, Quad2, aGL, Handle(IntPatch_RLine)::DownCast(slini), TolArc);
+ }
+
+ if (HasToDeleteRLine)
+ {
+ break;
+ }
+ }
+ } //-- if (typ2 != IntPatch_Restriction)
+ } //-- for (j=1; j<=Nblin; j++)
+ } //-- if (typ1 == IntPatch_Restriction)
+
+ if (HasToDeleteRLine)
+ {
+ slin.Remove(i);
+ i--;
+ Nblin = slin.Length();
+ continue;
+ }
+ } //-- for (i=1; i<=Nblin; i++)
+}
+
+static Standard_Boolean IntPP(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Real,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Boolean IntPCy(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ const Standard_Real H = 0.);
+
+static Standard_Boolean IntPSp(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ //modified by NIZNHY-PKV Tue Sep 20 08:59:56 2011t
+ const Standard_Real,
+ //modified by NIZNHY-PKV Tue Sep 20 08:59:52 2011t
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static Standard_Boolean IntPCo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static void ProcessBounds(const Handle(IntPatch_ALine)&,
+ const IntPatch_SequenceOfLine&,
+ const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ Standard_Boolean&,
+ const gp_Pnt&,
+ const Standard_Real,
+ Standard_Boolean&,
+ const gp_Pnt&,
+ const Standard_Real,
+ Standard_Boolean&,
+ const Standard_Real);
+
+static IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Bnd_Box2d& theUVSurf1,
+ const Bnd_Box2d& theUVSurf2,
+ Standard_Boolean& isTheEmpty,
+ Standard_Boolean& isTheSameSurface,
+ Standard_Boolean& isTheMultiplePoint,
+ IntPatch_SequenceOfLine& theSlin,
+ IntPatch_SequenceOfPoint& theSPnt);
+
+static Standard_Boolean IntCySp(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static Standard_Boolean IntCyCo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static Standard_Boolean IntSpSp(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static Standard_Boolean IntCoSp(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+static Standard_Boolean IntCoCo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&,
+ IntPatch_SequenceOfPoint&);
+
+//torus
+static Standard_Boolean IntPTo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Boolean IntCyTo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Boolean IntCoTo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Boolean IntSpTo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ const Standard_Boolean,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Boolean IntToTo(const IntSurf_Quadric&,
+ const IntSurf_Quadric&,
+ const Standard_Real,
+ Standard_Boolean&,
+ Standard_Boolean&,
+ IntPatch_SequenceOfLine&);
+
+static Standard_Integer SetQuad(const Handle(Adaptor3d_Surface)& theS, GeomAbs_SurfaceType& theTS, IntSurf_Quadric& theQuad);
+
+//=======================================================================
+//function : IntPatch_ImpImpIntersection
+//purpose :
+//=======================================================================
+IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection()
+: myDone(IntStatus_Fail),
+ empt(Standard_True),
+ tgte(Standard_False),
+ oppo(Standard_False)
+{}
+//=======================================================================
+//function : IntPatch_ImpImpIntersection
+//purpose :
+//=======================================================================
+IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection(const Handle(Adaptor3d_Surface)& S1,
+ const Handle(Adaptor3d_TopolTool)& D1,
+ const Handle(Adaptor3d_Surface)& S2,
+ const Handle(Adaptor3d_TopolTool)& D2,
+ const Standard_Real TolArc,
+ const Standard_Real TolTang,
+ const Standard_Boolean theIsReqToKeepRLine)
+{
+ Perform(S1, D1, S2, D2, TolArc, TolTang, theIsReqToKeepRLine);
+}
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_Surface)& S1,
+ const Handle(Adaptor3d_TopolTool)& D1,
+ const Handle(Adaptor3d_Surface)& S2,
+ const Handle(Adaptor3d_TopolTool)& D2,
+ const Standard_Real TolArc,
+ const Standard_Real TolTang,
+ const Standard_Boolean theIsReqToKeepRLine)
+{
+ myDone = IntStatus_Fail;
+ spnt.Clear();
+ slin.Clear();
+
+ Standard_Boolean isPostProcessingRequired = Standard_True;
+
+ empt = Standard_True;
+ tgte = Standard_False;
+ oppo = Standard_False;
+
+ Standard_Boolean all1 = Standard_False;
+ Standard_Boolean all2 = Standard_False;
+ Standard_Boolean SameSurf = Standard_False;
+ Standard_Boolean multpoint = Standard_False;
+
+ Standard_Boolean nosolonS1 = Standard_False;
+ // indique s il y a des points sur restriction du carreau 1
+ Standard_Boolean nosolonS2 = Standard_False;
+ // indique s il y a des points sur restriction du carreau 2
+ Standard_Integer i, nbpt, nbseg;
+ IntPatch_SequenceOfSegmentOfTheSOnBounds edg1, edg2;
+ IntPatch_SequenceOfPathPointOfTheSOnBounds pnt1, pnt2;
+ //
+ // On commence par intersecter les supports des surfaces
+ IntSurf_Quadric quad1, quad2;
+ IntPatch_ArcFunction AFunc;
+ const Standard_Real Tolang = 1.e-8;
+ GeomAbs_SurfaceType typs1, typs2;
+ Standard_Boolean bEmpty = Standard_False;
+ //
+ const Standard_Integer iT1 = SetQuad(S1, typs1, quad1);
+ const Standard_Integer iT2 = SetQuad(S2, typs2, quad2);
+ //
+ if (!iT1 || !iT2)
+ {
+ throw Standard_ConstructionError();
+ return;
+ }
+ //
+ const Standard_Boolean bReverse = iT1 > iT2;
+ const Standard_Integer iTT = iT1 * 10 + iT2;
+ //
+ switch (iTT)
+ {
+ case 11:
+ { // Plane/Plane
+ if (!IntPP(quad1, quad2, Tolang, TolTang, SameSurf, slin))
+ {
+ return;
+ }
+ break;
+ }
+ //
+ case 12:
+ case 21:
+ { // Plane/Cylinder
+ Standard_Real VMin, VMax, H;
+ //
+ const Handle(Adaptor3d_Surface)& aSCyl = bReverse ? S1 : S2;
+ VMin = aSCyl->FirstVParameter();
+ VMax = aSCyl->LastVParameter();
+ H = (Precision::IsNegativeInfinite(VMin) || Precision::IsPositiveInfinite(VMax)) ? 0 : (VMax - VMin);
+ //
+ if (!IntPCy(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, H))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 13:
+ case 31:
+ { // Plane/Cone
+ if (!IntPCo(quad1, quad2, Tolang, TolTang, bReverse, empt, multpoint, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 14:
+ case 41:
+ { // Plane/Sphere
+ if (!IntPSp(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 15:
+ case 51:
+ { // Plane/Torus
+ if (!IntPTo(quad1, quad2, TolTang, bReverse, empt, slin))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 22:
+ { // Cylinder/Cylinder
+ Bnd_Box2d aBox1, aBox2;
+
+ const Standard_Real aU1f = S1->FirstUParameter();
+ Standard_Real aU1l = S1->LastUParameter();
+ const Standard_Real aU2f = S2->FirstUParameter();
+ Standard_Real aU2l = S2->LastUParameter();
+
+ const Standard_Real anUperiod = 2.0 * M_PI;
+
+ if (aU1l - aU1f > anUperiod)
+ aU1l = aU1f + anUperiod;
+
+ if (aU2l - aU2f > anUperiod)
+ aU2l = aU2f + anUperiod;
+
+ aBox1.Add(gp_Pnt2d(aU1f, S1->FirstVParameter()));
+ aBox1.Add(gp_Pnt2d(aU1l, S1->LastVParameter()));
+ aBox2.Add(gp_Pnt2d(aU2f, S2->FirstVParameter()));
+ aBox2.Add(gp_Pnt2d(aU2l, S2->LastVParameter()));
+
+ // Resolution is too big if the cylinder radius is
+ // too small. Therefore, we shall bind its value above.
+ // Here, we use simple constant.
+ const Standard_Real a2DTol = Min(1.0e-4, Min(S1->UResolution(TolTang), S2->UResolution(TolTang)));
+
+ myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2, empt, SameSurf, multpoint, slin, spnt);
+
+ if (myDone == IntPatch_ImpImpIntersection::IntStatus_Fail)
+ {
+ return;
+ }
+
+ bEmpty = empt;
+ if (!slin.IsEmpty())
+ {
+ const Handle(IntPatch_WLine)& aWLine = Handle(IntPatch_WLine)::DownCast(slin.Value(1));
+
+ if (!aWLine.IsNull())
+ { //No geometric solution
+ isPostProcessingRequired = Standard_False;
+ }
+ }
+
+ break;
+ }
+ //
+ case 23:
+ case 32:
+ { // Cylinder/Cone
+ if (!IntCyCo(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 24:
+ case 42:
+ { // Cylinder/Sphere
+ if (!IntCySp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 25:
+ case 52:
+ { // Cylinder/Torus
+ if (!IntCyTo(quad1, quad2, TolTang, bReverse, empt, slin))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 33:
+ { // Cone/Cone
+ if (!IntCoCo(quad1, quad2, TolTang, empt, SameSurf, multpoint, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 34:
+ case 43:
+ { // Cone/Sphere
+ if (!IntCoSp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 35:
+ case 53:
+ { // Cone/Torus
+ if (!IntCoTo(quad1, quad2, TolTang, bReverse, empt, slin))
+ {
+ return;
+ }
+ break;
+ }
+ //
+ case 44:
+ { // Sphere/Sphere
+ if (!IntSpSp(quad1, quad2, TolTang, empt, SameSurf, slin, spnt))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 45:
+ case 54:
+ { // Sphere/Torus
+ if (!IntSpTo(quad1, quad2, TolTang, bReverse, empt, slin))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ case 55:
+ { // Torus/Torus
+ if (!IntToTo(quad1, quad2, TolTang, SameSurf, empt, slin))
+ {
+ return;
+ }
+ bEmpty = empt;
+ break;
+ }
+ //
+ default:
+ {
+ throw Standard_ConstructionError();
+ break;
+ }
+ }
+ //
+ if (bEmpty)
+ {
+ if (myDone == IntStatus_Fail)
+ myDone = IntStatus_OK;
+
+ return;
+ }
+ //
+
+ if (isPostProcessingRequired)
+ {
+ if (!SameSurf)
+ {
+ AFunc.SetQuadric(quad2);
+ AFunc.Set(S1);
+
+ solrst.Perform(AFunc, D1, TolArc, TolTang);
+ if (!solrst.IsDone())
+ {
+ return;
+ }
+
+ if (solrst.AllArcSolution() && typs1 == typs2)
+ {
+ all1 = Standard_True;
+ }
+ nbpt = solrst.NbPoints();
+ nbseg = solrst.NbSegments();
+ for (i = 1; i <= nbpt; i++)
+ {
+ const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
+ pnt1.Append(aPt);
+ }
+ for (i = 1; i <= nbseg; i++)
+ {
+ const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
+ edg1.Append(aSegm);
+ }
+ nosolonS1 = (nbpt == 0) && (nbseg == 0);
+
+ if (nosolonS1 && all1)
+ { // cas de face sans restrictions
+ all1 = Standard_False;
+ }
+ } //if (!SameSurf) {
+ else
+ {
+ nosolonS1 = Standard_True;
+ }
+
+ if (!SameSurf)
+ {
+ AFunc.SetQuadric(quad1);
+ AFunc.Set(S2);
+
+ solrst.Perform(AFunc, D2, TolArc, TolTang);
+ if (!solrst.IsDone())
+ {
+ return;
+ }
+
+ if (solrst.AllArcSolution() && typs1 == typs2)
+ {
+ all2 = Standard_True;
+ }
+
+ nbpt = solrst.NbPoints();
+ nbseg = solrst.NbSegments();
+ for (i = 1; i <= nbpt; i++)
+ {
+ const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
+ pnt2.Append(aPt);
+ }
+
+ for (i = 1; i <= nbseg; i++)
+ {
+ const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
+ edg2.Append(aSegm);
+ }
+
+ nosolonS2 = (nbpt == 0) && (nbseg == 0);
+
+ if (nosolonS2 && all2)
+ { // cas de face sans restrictions
+ all2 = Standard_False;
+ }
+ } // if (!SameSurf) {
+ else
+ {
+ nosolonS2 = Standard_True;
+ }
+ //
+ if (SameSurf || (all1 && all2))
+ {
+ // faces "paralleles" parfaites
+ empt = Standard_False;
+ tgte = Standard_True;
+ slin.Clear();
+ spnt.Clear();
+
+ gp_Pnt Ptreference;
+
+ switch (typs1)
+ {
+ case GeomAbs_Plane:
+ {
+ Ptreference = (S1->Plane()).Location();
+ }
+ break;
+ case GeomAbs_Cylinder:
+ {
+ Ptreference = ElSLib::Value(0., 0., S1->Cylinder());
+ }
+ break;
+ case GeomAbs_Sphere:
+ {
+ Ptreference = ElSLib::Value(M_PI / 4., M_PI / 4., S1->Sphere());
+ }
+ break;
+ case GeomAbs_Cone:
+ {
+ Ptreference = ElSLib::Value(0., 10., S1->Cone());
+ }
+ break;
+ case GeomAbs_Torus:
+ {
+ Ptreference = ElSLib::Value(0., 0., S1->Torus());
+ }
+ break;
+ default: break;
+ }
+ //
+ oppo = quad1.Normale(Ptreference).Dot(quad2.Normale(Ptreference)) < 0.0;
+ myDone = IntStatus_OK;
+ return;
+ } // if (SameSurf || (all1 && all2)) {
+
+ if (!nosolonS1 || !nosolonS2)
+ {
+ empt = Standard_False;
+ // C est la qu il faut commencer a bosser...
+ PutPointsOnLine(S1, S2, pnt1, slin, Standard_True, D1, quad1, quad2, multpoint, TolArc);
+
+ PutPointsOnLine(S1, S2, pnt2, slin, Standard_False, D2, quad2, quad1, multpoint, TolArc);
+
+ if (edg1.Length() != 0)
+ {
+ ProcessSegments(edg1, slin, quad1, quad2, Standard_True, TolArc);
+ }
+
+ if (edg2.Length() != 0)
+ {
+ ProcessSegments(edg2, slin, quad1, quad2, Standard_False, TolArc);
+ }
+
+ if (edg1.Length() != 0 || edg2.Length() != 0)
+ {
+ // ProcessRLine(slin,S1,S2,TolArc);
+ ProcessRLine(slin, quad1, quad2, TolArc, theIsReqToKeepRLine);
+ }
+ } //if (!nosolonS1 || !nosolonS2) {
+ else
+ {
+ empt = ((slin.Length() == 0) && (spnt.Length() == 0));
+ }
+ }
+
+ Standard_Integer nblin = slin.Length(), aNbPnt = spnt.Length();
+ //
+ //modified by NIZNHY-PKV Tue Sep 06 10:03:35 2011f
+ if (aNbPnt)
+ {
+ IntPatch_SequenceOfPoint aSIP;
+ //
+ for (i = 1; i <= aNbPnt; ++i)
+ {
+ Standard_Real aU1, aV1, aU2, aV2;
+ gp_Pnt2d aP2D;
+ TopAbs_State aState1, aState2;
+ //
+ const IntPatch_Point& aIP = spnt(i);
+ aIP.Parameters(aU1, aV1, aU2, aV2);
+ //
+ aP2D.SetCoord(aU1, aV1);
+ aState1 = D1->Classify(aP2D, TolArc);
+ //
+ aP2D.SetCoord(aU2, aV2);
+ aState2 = D2->Classify(aP2D, TolArc);
+ //
+ if (aState1 != TopAbs_OUT && aState2 != TopAbs_OUT)
+ {
+ aSIP.Append(aIP);
+ }
+ }
+ //
+ spnt.Clear();
+ //
+ aNbPnt = aSIP.Length();
+ for (i = 1; i <= aNbPnt; ++i)
+ {
+ const IntPatch_Point& aIP = aSIP(i);
+ spnt.Append(aIP);
+ }
+ //
+ } // if (aNbPnt) {
+ //modified by NIZNHY-PKV Tue Sep 06 10:18:20 2011t
+ //
+ for (i = 1; i <= nblin; i++)
+ {
+ IntPatch_IType thetype = slin.Value(i)->ArcType();
+ if ((thetype == IntPatch_Ellipse) || (thetype == IntPatch_Circle) || (thetype == IntPatch_Lin)
+ || (thetype == IntPatch_Parabola) || (thetype == IntPatch_Hyperbola))
+ {
+ Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
+ glin->ComputeVertexParameters(TolArc);
+ }
+ else if (thetype == IntPatch_Analytic)
+ {
+ Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(i));
+ aligold->ComputeVertexParameters(TolArc);
+ }
+ else if (thetype == IntPatch_Restriction)
+ {
+ Handle(IntPatch_RLine)& rlig = *((Handle(IntPatch_RLine)*)&slin.Value(i));
+ rlig->ComputeVertexParameters(TolArc);
+ }
+ }
+ //
+ //----------------------------------------------------------------
+ //-- On place 2 vertex sur les courbes de GLine qui n en
+ //-- contiennent pas.
+ for (i = 1; i <= nblin; i++)
+ {
+ gp_Pnt P;
+ IntPatch_Point point;
+ Standard_Real u1, v1, u2, v2;
+ if (slin.Value(i)->ArcType() == IntPatch_Circle)
+ {
+ const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
+ if (glin->NbVertex() == 0)
+ {
+ gp_Circ Circ = glin->Circle();
+ P = ElCLib::Value(0.0, Circ);
+ quad1.Parameters(P, u1, v1);
+ quad2.Parameters(P, u2, v2);
+ point.SetValue(P, TolArc, Standard_False);
+ point.SetParameters(u1, v1, u2, v2);
+ point.SetParameter(0.0);
+ glin->AddVertex(point);
+
+ P = ElCLib::Value(0.0, Circ);
+ quad1.Parameters(P, u1, v1);
+ quad2.Parameters(P, u2, v2);
+ point.SetValue(P, TolArc, Standard_False);
+ point.SetParameters(u1, v1, u2, v2);
+ point.SetParameter(M_PI + M_PI);
+ glin->AddVertex(point);
+ }
+ }
+
+ else if (slin.Value(i)->ArcType() == IntPatch_Ellipse)
+ {
+ const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
+ if (glin->NbVertex() == 0)
+ {
+ gp_Elips Elips = glin->Ellipse();
+ P = ElCLib::Value(0.0, Elips);
+ quad1.Parameters(P, u1, v1);
+ quad2.Parameters(P, u2, v2);
+ point.SetValue(P, TolArc, Standard_False);
+ point.SetParameters(u1, v1, u2, v2);
+ point.SetParameter(0.0);
+ glin->AddVertex(point);
+
+ P = ElCLib::Value(0.0, Elips);
+ quad1.Parameters(P, u1, v1);
+ quad2.Parameters(P, u2, v2);
+ point.SetValue(P, TolArc, Standard_False);
+ point.SetParameters(u1, v1, u2, v2);
+ point.SetParameter(M_PI + M_PI);
+ glin->AddVertex(point);
+ }
+ }
+ }
+ myDone = IntStatus_OK;
+}
+
+//=======================================================================
+//function : SetQuad
+//purpose :
+//=======================================================================
+Standard_Integer SetQuad(const Handle(Adaptor3d_Surface)& theS, GeomAbs_SurfaceType& theTS, IntSurf_Quadric& theQuad)
+{
+ theTS = theS->GetType();
+ Standard_Integer iRet = 0;
+ switch (theTS)
+ {
+ case GeomAbs_Plane:
+ theQuad.SetValue(theS->Plane());
+ iRet = 1;
+ break;
+ case GeomAbs_Cylinder:
+ theQuad.SetValue(theS->Cylinder());
+ iRet = 2;
+ break;
+ case GeomAbs_Cone:
+ theQuad.SetValue(theS->Cone());
+ iRet = 3;
+ break;
+ case GeomAbs_Sphere:
+ theQuad.SetValue(theS->Sphere());
+ iRet = 4;
+ break;
+ case GeomAbs_Torus:
+ theQuad.SetValue(theS->Torus());
+ iRet = 5;
+ break;
+ default: break;
+ }
+ //
+ return iRet;
+}
+
+static void SeamPosition(const gp_Pnt& aPLoc, const gp_Ax3& aPos, gp_Ax2& aSeamPos);
+static void AdjustToSeam(const gp_Cylinder& aQuad, gp_Circ& aCirc);
+static void AdjustToSeam(const gp_Sphere& aQuad, gp_Circ& aCirc, const Standard_Real aTolAng);
+static void AdjustToSeam(const gp_Cone& aQuad, gp_Circ& aCirc);
+static void AdjustToSeam(const gp_Torus& aQuad, gp_Circ& aCirc);
+//modified by NIZNHY-PKV Thu Sep 15 11:09:13 2011
+
+//=======================================================================
+//function : IntPP
+//purpose :
+// Traitement du cas Plan/Plan
+//=======================================================================
+Standard_Boolean IntPP(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tolang,
+ const Standard_Real TolTang,
+ Standard_Boolean& Same,
+ IntPatch_SequenceOfLine& slin)
+
+{
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+ gp_Pln pl1(Quad1.Plane());
+ gp_Pln pl2(Quad2.Plane());
+
+ IntAna_QuadQuadGeo inter(pl1, pl2, Tolang, TolTang);
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+ Same = Standard_False;
+ typint = inter.TypeInter();
+ if (typint == IntAna_Same)
+ { // cas faces confondues
+ Same = Standard_True;
+ }
+ else if (typint != IntAna_Empty)
+ { // on a une ligne
+ gp_Lin linsol = inter.Line(1);
+ Standard_Real discri = linsol.Direction().DotCross(Quad2.Normale(linsol.Location()), Quad1.Normale(linsol.Location()));
+
+ if (discri > 0.0)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ return Standard_True;
+}
+//=======================================================================
+//function : IntPCy
+//purpose :
+// Traitement du cas Plan/Cylindre et reciproquement
+//=======================================================================
+Standard_Boolean IntPCy(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tolang,
+ const Standard_Real TolTang,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ IntPatch_SequenceOfLine& slin,
+ const Standard_Real H)
+
+{
+ gp_Pln Pl;
+ gp_Cylinder Cy;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+
+ IntAna_QuadQuadGeo inter;
+ if (!Reversed)
+ {
+ Pl = Quad1.Plane();
+ Cy = Quad2.Cylinder();
+ }
+ else
+ {
+ Pl = Quad2.Plane();
+ Cy = Quad1.Cylinder();
+ }
+ inter.Perform(Pl, Cy, Tolang, TolTang, H);
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+ typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Line:
+ {
+ gp_Lin linsol = inter.Line(1);
+ gp_Pnt orig(linsol.Location());
+ if (NbSol == 1)
+ { // ligne de tangence
+ gp_Vec TestCurvature(orig, Cy.Location());
+ gp_Vec Normp, Normcyl;
+ if (!Reversed)
+ {
+ Normp = Quad1.Normale(orig);
+ Normcyl = Quad2.Normale(orig);
+ }
+ else
+ {
+ Normp = Quad2.Normale(orig);
+ Normcyl = Quad1.Normale(orig);
+ }
+
+ IntSurf_Situation situcyl;
+ IntSurf_Situation situp;
+
+ if (Normp.Dot(TestCurvature) > 0.)
+ {
+ situcyl = IntSurf_Outside;
+ if (Normp.Dot(Normcyl) > 0.)
+ {
+ situp = IntSurf_Inside;
+ }
+ else
+ {
+ situp = IntSurf_Outside;
+ }
+ }
+ else
+ {
+ situcyl = IntSurf_Inside;
+ if (Normp.Dot(Normcyl) > 0.)
+ {
+ situp = IntSurf_Outside;
+ }
+ else
+ {
+ situp = IntSurf_Inside;
+ }
+ }
+ Handle(IntPatch_GLine) glig;
+ if (!Reversed)
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situp, situcyl);
+ }
+ else
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situcyl, situp);
+ }
+ slin.Append(glig);
+ }
+ else
+ {
+ // on a 2 droites. Il faut determiner les transitions
+ // de chacune.
+
+ if (linsol.Direction().DotCross(Quad2.Normale(orig), Quad1.Normale(orig)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+
+ linsol = inter.Line(2);
+ orig = linsol.Location();
+
+ if (linsol.Direction().DotCross(Quad2.Normale(orig), Quad1.Normale(orig)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ }
+ break;
+ //
+ case IntAna_Circle:
+ {
+ gp_Circ cirsol;
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ //
+ cirsol = inter.Circle(1);
+ //modified by NIZNHY-PKV Thu Sep 15 11:30:03 2011f
+ AdjustToSeam(Cy, cirsol);
+ //modified by NIZNHY-PKV Thu Sep 15 11:30:15 2011t
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.0)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+ //
+ case IntAna_Ellipse:
+ {
+ gp_Elips elipsol = inter.Ellipse(1);
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ ElCLib::D1(0., elipsol, ptref, Tgt);
+
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.0)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+ //
+ default:
+ {
+ return Standard_False; // on ne doit pas passer ici
+ }
+ }
+ return Standard_True;
+}
+//=======================================================================
+//function : IntPSp
+//purpose :
+// Traitement du cas Plan/Sphere et reciproquement
+//=======================================================================
+Standard_Boolean IntPSp(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ //modified by NIZNHY-PKV Tue Sep 20 08:59:36 2011f
+ const Standard_Real Tolang,
+ //modified by NIZNHY-PKV Tue Sep 20 08:59:39 2011t
+ const Standard_Real TolTang,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ gp_Circ cirsol;
+ gp_Pln Pl;
+ gp_Sphere Sp;
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+
+ IntAna_QuadQuadGeo inter;
+ if (!Reversed)
+ {
+ Pl = Quad1.Plane();
+ Sp = Quad2.Sphere();
+ }
+ else
+ {
+ Pl = Quad2.Plane();
+ Sp = Quad1.Sphere();
+ }
+ inter.Perform(Pl, Sp);
+
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+
+ typint = inter.TypeInter();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+ //
+ case IntAna_Point:
+ {
+ gp_Pnt psol = inter.Point(1);
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(psol, TolTang, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+ //
+ case IntAna_Circle:
+ {
+ cirsol = inter.Circle(1);
+ //modified by NIZNHY-PKV Thu Sep 15 11:30:03 2011f
+ AdjustToSeam(Sp, cirsol, Tolang);
+ //modified by NIZNHY-PKV Thu Sep 15 11:30:15 2011t
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ default:
+ {
+ return Standard_False; // on ne doit pas passer ici
+ }
+ }
+ return Standard_True;
+}
+//=======================================================================
+//function : IntPCo
+//purpose :
+// Traitement du cas Plan/Cone et reciproquement
+//=======================================================================
+Standard_Boolean IntPCo(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tolang,
+ const Standard_Real TolTang,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ gp_Pnt apex;
+
+ gp_Pln Pl;
+ gp_Cone Co;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+
+ IntAna_QuadQuadGeo inter;
+ if (!Reversed)
+ {
+ Pl = Quad1.Plane();
+ Co = Quad2.Cone();
+ apex = Co.Apex();
+ }
+ else
+ {
+ Pl = Quad2.Plane();
+ Co = Quad1.Cone();
+ apex = Co.Apex();
+ }
+
+ inter.Perform(Pl, Co, Tolang, TolTang);
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+ //
+ typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Point:
+ {
+ gp_Pnt psol = inter.Point(1);
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(psol, TolTang, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+
+ case IntAna_Line:
+ {
+ gp_Lin linsol = inter.Line(1);
+ if (linsol.Direction().Dot(Co.Axis().Direction()) < 0.)
+ {
+ linsol.SetDirection(linsol.Direction().Reversed());
+ }
+ Standard_Real para = ElCLib::Parameter(linsol, apex);
+ gp_Pnt ptbid(ElCLib::Value(para + 5., linsol));
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(apex, U1, V1);
+ Quad2.Parameters(apex, U2, V2);
+
+ if (NbSol == 1)
+ { // ligne de tangence
+ IntPatch_Point ptsol;
+ ptsol.SetValue(apex, TolTang, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(para);
+ gp_Pnt ptbid2(apex.XYZ() + 5. * Co.Axis().Direction().XYZ());
+ gp_Vec TestCurvature(ptbid, ptbid2);
+ gp_Vec Normp, Normco;
+ if (!Reversed)
+ {
+ Normp = Quad1.Normale(ptbid);
+ Normco = Quad2.Normale(ptbid);
+ }
+ else
+ {
+ Normp = Quad2.Normale(ptbid);
+ Normco = Quad1.Normale(ptbid);
+ }
+ IntSurf_Situation situco, situco_otherside;
+ IntSurf_Situation situp, situp_otherside;
+
+ if (Normp.Dot(TestCurvature) > 0.)
+ {
+ situco = IntSurf_Outside;
+ situco_otherside = IntSurf_Inside;
+ if (Normp.Dot(Normco) > 0.)
+ {
+ situp = IntSurf_Inside;
+ situp_otherside = IntSurf_Outside;
+ }
+ else
+ {
+ situp = IntSurf_Outside;
+ situp_otherside = IntSurf_Inside;
+ }
+ }
+ else
+ {
+ situco = IntSurf_Inside;
+ situco_otherside = IntSurf_Outside;
+ if (Normp.Dot(Normco) > 0.)
+ {
+ situp = IntSurf_Outside;
+ situp_otherside = IntSurf_Inside;
+ }
+ else
+ {
+ situp = IntSurf_Inside;
+ situp_otherside = IntSurf_Outside;
+ }
+ }
+ //----------------------------------------------------------
+ //-- Apex ---> Cone.Direction
+ //--
+ Handle(IntPatch_GLine) glig;
+ if (!Reversed)
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situp, situco);
+ }
+ else
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situco, situp);
+ }
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ //----------------------------------------------------------
+ //-- -Cone.Direction <------- Apex
+ //--
+ linsol.SetDirection(linsol.Direction().Reversed());
+ if (!Reversed)
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situp_otherside, situco_otherside);
+ }
+ else
+ {
+ glig = new IntPatch_GLine(linsol, Standard_True, situco_otherside, situp_otherside);
+ }
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ }
+ else
+ {
+ // on a 2 droites. Il faut determiner les transitions
+ // de chacune. On oriente chaque ligne dans le sens
+ // de l axe du cone. Les transitions de chaque ligne seront
+ // inverses l une de l autre => on ne fait le calcul que sur
+ // la premiere.
+ if (linsol.Direction().DotCross(Quad2.Normale(ptbid), Quad1.Normale(ptbid)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+
+ Multpoint = Standard_True;
+ //------------------------------------------- Ligne 1 -------
+ IntPatch_Point ptsol;
+ ptsol.SetValue(apex, TolTang, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(para);
+ ptsol.SetMultiple(Standard_True);
+ Handle(IntPatch_GLine) glig;
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ //-----------------------------------------------------------
+ //-- Other Side : Les transitions restent les memes
+ //-- linsol -> -linsol et Quad1(2).N -> -Quad1(2).N
+ //--
+ linsol.SetDirection(linsol.Direction().Reversed());
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ para = ElCLib::Parameter(linsol, apex);
+ ptsol.SetParameter(para);
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+
+ //------------------------------------------- Ligne 2 -------
+ linsol = inter.Line(2);
+ if (linsol.Direction().Dot(Co.Axis().Direction()) < 0.)
+ {
+ linsol.SetDirection(linsol.Direction().Reversed());
+ }
+ para = ElCLib::Parameter(linsol, apex);
+ ptbid = ElCLib::Value(para + 5., linsol);
+ if (linsol.Direction().DotCross(Quad2.Normale(ptbid), Quad1.Normale(ptbid)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ ptsol.SetParameter(para);
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ para = ElCLib::Parameter(linsol, apex);
+ ptsol.SetParameter(para);
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ //-----------------------------------------------------------
+ //-- Other Side : Les transitions restent les memes
+ //-- linsol -> -linsol et Quad1(2).N -> -Quad1(2).N
+ //--
+ linsol.SetDirection(linsol.Direction().Reversed());
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ para = ElCLib::Parameter(linsol, apex);
+ ptsol.SetParameter(para);
+ glig->AddVertex(ptsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ gp_Circ cirsol = inter.Circle(1);
+ //modified by NIZNHY-PKV Thu Sep 15 11:34:04 2011f
+ AdjustToSeam(Co, cirsol);
+ //modified by NIZNHY-PKV Thu Sep 15 11:36:08 2011t
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_Ellipse:
+ {
+ gp_Elips elipsol = inter.Ellipse(1);
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ ElCLib::D1(0., elipsol, ptref, Tgt);
+
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_Parabola:
+ {
+ gp_Parab parabsol = inter.Parabola(1);
+
+ gp_Vec Tgtorig(parabsol.YAxis().Direction());
+ Standard_Real ptran = Tgtorig.DotCross(Quad2.Normale(parabsol.Location()), Quad1.Normale(parabsol.Location()));
+ if (ptran > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (ptran < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(parabsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_Hyperbola:
+ {
+ gp_Pnt tophypr;
+ gp_Vec Tgttop;
+
+ for (Standard_Integer i = 1; i <= 2; i++)
+ {
+ gp_Hypr hyprsol = inter.Hyperbola(i);
+ tophypr = ElCLib::Value(hyprsol.MajorRadius(), hyprsol.XAxis());
+ Tgttop = hyprsol.YAxis().Direction();
+ Standard_Real qwe = Tgttop.DotCross(Quad2.Normale(tophypr), Quad1.Normale(tophypr));
+
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(hyprsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ default:
+ {
+ return Standard_False;
+ }
+ }
+ return Standard_True;
+}
+//=======================================================================
+//function : IntPTo
+//purpose :
+//=======================================================================
+Standard_Boolean IntPTo(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTolTang,
+ const Standard_Boolean bReversed,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ const gp_Pln aPln = bReversed ? theQuad2.Plane() : theQuad1.Plane();
+ const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
+ //
+ IntAna_QuadQuadGeo inter(aPln, aTorus, theTolTang);
+ Standard_Boolean bRet = inter.IsDone();
+ //
+ if (!bRet)
+ {
+ return bRet;
+ }
+ //
+ IntAna_ResultType typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ bEmpty = Standard_False;
+ //
+ switch (typint)
+ {
+ case IntAna_Empty: bEmpty = Standard_True; break;
+ //
+ case IntAna_Circle:
+ {
+ Standard_Integer i;
+ IntSurf_TypeTrans trans1, trans2;
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ //
+ for (i = 1; i <= NbSol; ++i)
+ {
+ gp_Circ aC = inter.Circle(i);
+ if (!aPln.Axis().IsNormal(aTorus.Axis(), Precision::Angular()))
+ {
+ AdjustToSeam(aTorus, aC);
+ }
+ ElCLib::D1(0., aC, ptref, Tgt);
+ //
+ if (Tgt.DotCross(theQuad2.Normale(ptref), theQuad1.Normale(ptref)) > 0.0)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ //
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(aC, Standard_False, trans1, trans2);
+ theSeqLin.Append(glig);
+ }
+ }
+ break;
+ //
+ case IntAna_NoGeometricSolution:
+ default: bRet = Standard_False; break;
+ }
+ //
+ return bRet;
+}
+//
+//modified by NIZNHY-PKV Thu Sep 15 10:53:39 2011f
+//=======================================================================
+//function : AdjustToSeam
+//purpose :
+//=======================================================================
+void AdjustToSeam(const gp_Cone& aQuad, gp_Circ& aCirc)
+{
+ gp_Ax2 aAx2;
+ //
+ const gp_Pnt& aPLoc = aCirc.Location();
+ const gp_Ax3& aAx3 = aQuad.Position();
+ SeamPosition(aPLoc, aAx3, aAx2);
+ aCirc.SetPosition(aAx2);
+}
+//=======================================================================
+//function : AdjustToSeam
+//purpose :
+//=======================================================================
+void AdjustToSeam(const gp_Sphere& aQuad, gp_Circ& aCirc, const Standard_Real aTolAng)
+{
+ gp_Ax2 aAx2;
+ //
+ const gp_Ax1& aAx1C = aCirc.Axis();
+ const gp_Ax3& aAx3 = aQuad.Position();
+ const gp_Ax1& aAx1Q = aAx3.Axis();
+ //
+ const gp_Dir& aDirC = aAx1C.Direction();
+ const gp_Dir& aDirQ = aAx1Q.Direction();
+ if (aDirC.IsParallel(aDirQ, aTolAng))
+ {
+ const gp_Pnt& aPLoc = aCirc.Location();
+ SeamPosition(aPLoc, aAx3, aAx2);
+ aCirc.SetPosition(aAx2);
+ }
+}
+//=======================================================================
+//function : AdjustToSeam
+//purpose :
+//=======================================================================
+void AdjustToSeam(const gp_Cylinder& aQuad, gp_Circ& aCirc)
+{
+ gp_Ax2 aAx2;
+ //
+ const gp_Pnt& aPLoc = aCirc.Location();
+ const gp_Ax3& aAx3 = aQuad.Position();
+ SeamPosition(aPLoc, aAx3, aAx2);
+ aCirc.SetPosition(aAx2);
+}
+//=======================================================================
+//function : AdjustToSeam
+//purpose :
+//=======================================================================
+void AdjustToSeam(const gp_Torus& aQuad, gp_Circ& aCirc)
+{
+ gp_Ax2 aAx2;
+ //
+ const gp_Pnt& aPLoc = aCirc.Location();
+ const gp_Ax3& aAx3 = aQuad.Position();
+ SeamPosition(aPLoc, aAx3, aAx2);
+ aCirc.SetPosition(aAx2);
+}
+//=======================================================================
+//function : SeamPosition
+//purpose :
+//=======================================================================
+void SeamPosition(const gp_Pnt& aPLoc, const gp_Ax3& aPos, gp_Ax2& aSeamPos)
+{
+ const gp_Dir& aDZ = aPos.Direction();
+ const gp_Dir& aDX = aPos.XDirection();
+ gp_Ax2 aAx2(aPLoc, aDZ, aDX);
+ aSeamPos = aAx2;
+}
+
+//modified by NIZNHY-PKV Thu Sep 15 10:53:41 2011t
+
+//If Abs(a) <= aNulValue then it is considered that a = 0.
+static const Standard_Real aNulValue = 1.0e-11;
+
+static void ShortCosForm(const Standard_Real theCosFactor,
+ const Standard_Real theSinFactor,
+ Standard_Real& theCoeff,
+ Standard_Real& theAngle);
+//
+static Standard_Boolean ExploreCurve(const gp_Cone& theCo, IntAna_Curve& aC, const Standard_Real aTol, IntAna_ListOfCurve& aLC);
+
+static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
+ const Standard_Real theUlTarget,
+ Standard_Real& theUGiven,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriod,
+ const Standard_Boolean theFlForce);
+
+class ComputationMethods
+{
+ //Every cylinder can be represented by the following equation in parametric form:
+ // S(U,V) = L + R*cos(U)*Xd+R*sin(U)*Yd+V*Zd,
+ //where location L, directions Xd, Yd and Zd have type gp_XYZ.
+
+ //Intersection points between two cylinders can be found from the following system:
+ // S1(U1, V1) = S2(U2, V2)
+ //or
+ // {X01 + R1*cos(U1)*Xx1 + R1*sin(U1)*Yx1 + V1*Zx1 = X02 + R2*cos(U2)*Xx2 + R2*sin(U2)*Yx2 + V2*Zx2
+ // {Y01 + R1*cos(U1)*Xy1 + R1*sin(U1)*Yy1 + V1*Zy1 = Y02 + R2*cos(U2)*Xy2 + R2*sin(U2)*Yy2 + V2*Zy2 (1)
+ // {Z01 + R1*cos(U1)*Xz1 + R1*sin(U1)*Yz1 + V1*Zz1 = Z02 + R2*cos(U2)*Xz2 + R2*sin(U2)*Yz2 + V2*Zz2
+
+ //The formula (1) can be rewritten as follows
+ // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1
+ // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2 (2)
+ // {C13*V1+C23*V2=A13*cos(U1)+B13*sin(U1)+A23*cos(U2)+B23*sin(U2)+D3
+
+ //Hereafter we consider that in system
+ // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1 (3)
+ // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2
+ //variables V1 and V2 can be found unambiguously, i.e. determinant
+ // |C11 C21|
+ // | | != 0
+ // |C12 C22|
+ //
+ //In this case, variables V1 and V2 can be found as follows:
+ // {V1 = K11*sin(U1)+K21*sin(U2)+L11*cos(U1)+L21*cos(U2)+M1 = K1*cos(U1-FIV1)+L1*cos(U2-PSIV1)+M1 (4)
+ // {V2 = K12*sin(U1)+K22*sin(U2)+L12*cos(U1)+L22*cos(U2)+M2 = K2*cos(U2-FIV2)+L2*cos(U2-PSIV2)+M2
+
+ //Having substituted result of (4) to the 3rd equation of (2), we will obtain equation
+ // cos(U2-FI2) = B*cos(U1-FI1)+C. (5)
+
+ //I.e. when U1 is taken different given values (from domain), correspond U2 value can be computed
+ //from equation (5). After that, V1 and V2 can be computed from the system (4) (see
+ //CylCylComputeParameters(...) methods).
+
+ //It is important to remark that equation (5) (in general) has two solutions: U2=FI2 +/- f(U1).
+ //Therefore, we are getting here two intersection lines.
+
+public:
+ //Stores equations coefficients
+ struct stCoeffsValue
+ {
+ stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
+
+ math_Vector mVecA1;
+ math_Vector mVecA2;
+ math_Vector mVecB1;
+ math_Vector mVecB2;
+ math_Vector mVecC1;
+ math_Vector mVecC2;
+ math_Vector mVecD;
+
+ Standard_Real mK21; //sinU2
+ Standard_Real mK11; //sinU1
+ Standard_Real mL21; //cosU2
+ Standard_Real mL11; //cosU1
+ Standard_Real mM1; //Free member
+
+ Standard_Real mK22; //sinU2
+ Standard_Real mK12; //sinU1
+ Standard_Real mL22; //cosU2
+ Standard_Real mL12; //cosU1
+ Standard_Real mM2; //Free member
+
+ Standard_Real mK1;
+ Standard_Real mL1;
+ Standard_Real mK2;
+ Standard_Real mL2;
+
+ Standard_Real mFIV1;
+ Standard_Real mPSIV1;
+ Standard_Real mFIV2;
+ Standard_Real mPSIV2;
+
+ Standard_Real mB;
+ Standard_Real mC;
+ Standard_Real mFI1;
+ Standard_Real mFI2;
+ };
+
+ //! Determines, if U2(U1) function is increasing.
+ static Standard_Boolean CylCylMonotonicity(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Standard_Boolean& theIsIncreasing);
+
+ //! Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
+ //! esimates the tolerance of U2-computing (estimation result is
+ //! assigned to *theDelta value).
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real* const theDelta = 0);
+
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1,
+ const Standard_Real theU2,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theV1,
+ Standard_Real& theV2);
+
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real& theV1,
+ Standard_Real& theV2);
+};
+
+ComputationMethods::stCoeffsValue::stCoeffsValue(const gp_Cylinder& theCyl1, const gp_Cylinder& theCyl2)
+: mVecA1(-theCyl1.Radius() * theCyl1.XAxis().Direction().XYZ()),
+ mVecA2(theCyl2.Radius() * theCyl2.XAxis().Direction().XYZ()),
+ mVecB1(-theCyl1.Radius() * theCyl1.YAxis().Direction().XYZ()),
+ mVecB2(theCyl2.Radius() * theCyl2.YAxis().Direction().XYZ()),
+ mVecC1(theCyl1.Axis().Direction().XYZ()),
+ mVecC2(theCyl2.Axis().Direction().XYZ().Reversed()),
+ mVecD(theCyl2.Location().XYZ() - theCyl1.Location().XYZ())
+{
+ enum CoupleOfEquation
+ {
+ COENONE = 0,
+ COE12 = 1,
+ COE23 = 2,
+ COE13 = 3
+ } aFoundCouple = COENONE;
+
+ Standard_Real aDetV1V2 = 0.0;
+
+ const Standard_Real aDelta1 = mVecC1(1) * mVecC2(2) - mVecC1(2) * mVecC2(1); //1-2
+ const Standard_Real aDelta2 = mVecC1(2) * mVecC2(3) - mVecC1(3) * mVecC2(2); //2-3
+ const Standard_Real aDelta3 = mVecC1(1) * mVecC2(3) - mVecC1(3) * mVecC2(1); //1-3
+ const Standard_Real anAbsD1 = Abs(aDelta1); //1-2
+ const Standard_Real anAbsD2 = Abs(aDelta2); //2-3
+ const Standard_Real anAbsD3 = Abs(aDelta3); //1-3
+
+ if (anAbsD1 >= anAbsD2)
+ {
+ if (anAbsD3 > anAbsD1)
+ {
+ aFoundCouple = COE13;
+ aDetV1V2 = aDelta3;
+ }
+ else
+ {
+ aFoundCouple = COE12;
+ aDetV1V2 = aDelta1;
+ }
+ }
+ else
+ {
+ if (anAbsD3 > anAbsD2)
+ {
+ aFoundCouple = COE13;
+ aDetV1V2 = aDelta3;
+ }
+ else
+ {
+ aFoundCouple = COE23;
+ aDetV1V2 = aDelta2;
+ }
+ }
+
+ // In point of fact, every determinant (aDelta1, aDelta2 and aDelta3) is
+ // cross-product between directions (i.e. sine of angle).
+ // If sine is too small then sine is (approx.) equal to angle itself.
+ // Therefore, in this case we should compare sine with angular tolerance.
+ // This constant is used for check if axes are parallel (see constructor
+ // AxeOperator::AxeOperator(...) in IntAna_QuadQuadGeo.cxx file).
+ if (Abs(aDetV1V2) < Precision::Angular())
+ {
+ throw Standard_Failure("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
+ }
+
+ switch (aFoundCouple)
+ {
+ case COE12: break;
+ case COE23:
+ {
+ math_Vector aVTemp(mVecA1);
+ mVecA1(1) = aVTemp(2);
+ mVecA1(2) = aVTemp(3);
+ mVecA1(3) = aVTemp(1);
+
+ aVTemp = mVecA2;
+ mVecA2(1) = aVTemp(2);
+ mVecA2(2) = aVTemp(3);
+ mVecA2(3) = aVTemp(1);
+
+ aVTemp = mVecB1;
+ mVecB1(1) = aVTemp(2);
+ mVecB1(2) = aVTemp(3);
+ mVecB1(3) = aVTemp(1);
+
+ aVTemp = mVecB2;
+ mVecB2(1) = aVTemp(2);
+ mVecB2(2) = aVTemp(3);
+ mVecB2(3) = aVTemp(1);
+
+ aVTemp = mVecC1;
+ mVecC1(1) = aVTemp(2);
+ mVecC1(2) = aVTemp(3);
+ mVecC1(3) = aVTemp(1);
+
+ aVTemp = mVecC2;
+ mVecC2(1) = aVTemp(2);
+ mVecC2(2) = aVTemp(3);
+ mVecC2(3) = aVTemp(1);
+
+ aVTemp = mVecD;
+ mVecD(1) = aVTemp(2);
+ mVecD(2) = aVTemp(3);
+ mVecD(3) = aVTemp(1);
+
+ break;
+ }
+ case COE13:
+ {
+ math_Vector aVTemp = mVecA1;
+ mVecA1(2) = aVTemp(3);
+ mVecA1(3) = aVTemp(2);
+
+ aVTemp = mVecA2;
+ mVecA2(2) = aVTemp(3);
+ mVecA2(3) = aVTemp(2);
+
+ aVTemp = mVecB1;
+ mVecB1(2) = aVTemp(3);
+ mVecB1(3) = aVTemp(2);
+
+ aVTemp = mVecB2;
+ mVecB2(2) = aVTemp(3);
+ mVecB2(3) = aVTemp(2);
+
+ aVTemp = mVecC1;
+ mVecC1(2) = aVTemp(3);
+ mVecC1(3) = aVTemp(2);
+
+ aVTemp = mVecC2;
+ mVecC2(2) = aVTemp(3);
+ mVecC2(3) = aVTemp(2);
+
+ aVTemp = mVecD;
+ mVecD(2) = aVTemp(3);
+ mVecD(3) = aVTemp(2);
+
+ break;
+ }
+ default: break;
+ }
+
+ //------- For V1 (begin)
+ //sinU2
+ mK21 = (mVecC2(2) * mVecB2(1) - mVecC2(1) * mVecB2(2)) / aDetV1V2;
+ //sinU1
+ mK11 = (mVecC2(2) * mVecB1(1) - mVecC2(1) * mVecB1(2)) / aDetV1V2;
+ //cosU2
+ mL21 = (mVecC2(2) * mVecA2(1) - mVecC2(1) * mVecA2(2)) / aDetV1V2;
+ //cosU1
+ mL11 = (mVecC2(2) * mVecA1(1) - mVecC2(1) * mVecA1(2)) / aDetV1V2;
+ //Free member
+ mM1 = (mVecC2(2) * mVecD(1) - mVecC2(1) * mVecD(2)) / aDetV1V2;
+ //------- For V1 (end)
+
+ //------- For V2 (begin)
+ //sinU2
+ mK22 = (mVecC1(1) * mVecB2(2) - mVecC1(2) * mVecB2(1)) / aDetV1V2;
+ //sinU1
+ mK12 = (mVecC1(1) * mVecB1(2) - mVecC1(2) * mVecB1(1)) / aDetV1V2;
+ //cosU2
+ mL22 = (mVecC1(1) * mVecA2(2) - mVecC1(2) * mVecA2(1)) / aDetV1V2;
+ //cosU1
+ mL12 = (mVecC1(1) * mVecA1(2) - mVecC1(2) * mVecA1(1)) / aDetV1V2;
+ //Free member
+ mM2 = (mVecC1(1) * mVecD(2) - mVecC1(2) * mVecD(1)) / aDetV1V2;
+ //------- For V1 (end)
+
+ ShortCosForm(mL11, mK11, mK1, mFIV1);
+ ShortCosForm(mL21, mK21, mL1, mPSIV1);
+ ShortCosForm(mL12, mK12, mK2, mFIV2);
+ ShortCosForm(mL22, mK22, mL2, mPSIV2);
+
+ const Standard_Real aA1 = mVecC1(3) * mK21 + mVecC2(3) * mK22 - mVecB2(3), //sinU2
+ aA2 = mVecC1(3) * mL21 + mVecC2(3) * mL22 - mVecA2(3), //cosU2
+ aB1 = mVecB1(3) - mVecC1(3) * mK11 - mVecC2(3) * mK12, //sinU1
+ aB2 = mVecA1(3) - mVecC1(3) * mL11 - mVecC2(3) * mL12; //cosU1
+
+ mC = mVecD(3) - mVecC1(3) * mM1 - mVecC2(3) * mM2; //Free
+
+ Standard_Real aA = 0.0;
+
+ ShortCosForm(aB2, aB1, mB, mFI1);
+ ShortCosForm(aA2, aA1, aA, mFI2);
+
+ mB /= aA;
+ mC /= aA;
+}
+
+class WorkWithBoundaries
+{
+public:
+ enum SearchBoundType
+ {
+ SearchNONE = 0,
+ SearchV1 = 1,
+ SearchV2 = 2
+ };
+
+ struct StPInfo
+ {
+ StPInfo()
+ {
+ mySurfID = 0;
+ myU1 = RealLast();
+ myV1 = RealLast();
+ myU2 = RealLast();
+ myV2 = RealLast();
+ }
+
+ //Equal to 0 for 1st surface non-zero for 2nd one.
+ Standard_Integer mySurfID;
+
+ Standard_Real myU1;
+ Standard_Real myV1;
+ Standard_Real myU2;
+ Standard_Real myV2;
+
+ bool operator>(const StPInfo& theOther) const { return myU1 > theOther.myU1; }
+
+ bool operator<(const StPInfo& theOther) const { return myU1 < theOther.myU1; }
+
+ bool operator==(const StPInfo& theOther) const { return myU1 == theOther.myU1; }
+ };
+
+ WorkWithBoundaries(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Bnd_Box2d& theUVSurf1,
+ const Bnd_Box2d& theUVSurf2,
+ const Standard_Integer theNbWLines,
+ const Standard_Real thePeriod,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Standard_Boolean isTheReverse)
+ : myQuad1(theQuad1),
+ myQuad2(theQuad2),
+ myCoeffs(theCoeffs),
+ myUVSurf1(theUVSurf1),
+ myUVSurf2(theUVSurf2),
+ myNbWLines(theNbWLines),
+ myPeriod(thePeriod),
+ myTol3D(theTol3D),
+ myTol2D(theTol2D),
+ myIsReverse(isTheReverse) {};
+
+ // Returns parameters of system solved while finding
+ // intersection line
+ const ComputationMethods::stCoeffsValue& SICoeffs() const { return myCoeffs; }
+
+ // Returns quadric correspond to the index theIdx.
+ const IntSurf_Quadric& GetQSurface(const Standard_Integer theIdx) const
+ {
+ if (theIdx <= 1)
+ return myQuad1;
+
+ return myQuad2;
+ }
+
+ // Returns TRUE in case of reverting surfaces
+ Standard_Boolean IsReversed() const { return myIsReverse; }
+
+ // Returns 2D-tolerance
+ Standard_Real Get2dTolerance() const { return myTol2D; }
+
+ // Returns 3D-tolerance
+ Standard_Real Get3dTolerance() const { return myTol3D; }
+
+ // Returns UV-bounds of 1st surface
+ const Bnd_Box2d& UVS1() const { return myUVSurf1; }
+
+ // Returns UV-bounds of 2nd surface
+ const Bnd_Box2d& UVS2() const { return myUVSurf2; }
+
+ void AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
+ const Standard_Real theU1,
+ const Standard_Real theU1Min,
+ const Standard_Real theU2,
+ const Standard_Real theV1,
+ const Standard_Real theV1Prev,
+ const Standard_Real theV2,
+ const Standard_Real theV2Prev,
+ const Standard_Integer theWLIndex,
+ const Standard_Boolean theFlForce,
+ Standard_Boolean& isTheFound1,
+ Standard_Boolean& isTheFound2) const;
+
+ static Standard_Boolean BoundariesComputing(const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Bnd_Range theURange[]);
+
+ void BoundaryEstimation(const gp_Cylinder& theCy1,
+ const gp_Cylinder& theCy2,
+ Bnd_Range& theOutBoxS1,
+ Bnd_Range& theOutBoxS2) const;
+
+protected:
+ //Solves equation (2) (see declaration of ComputationMethods class) in case,
+ //when V1 or V2 (is set by theSBType argument) is known (corresponds to the boundary
+ //and equal to theVzad) but U1 is unknown. Computation is made by numeric methods and
+ //requires initial values (theVInit, theInitU2 and theInitMainVar).
+ Standard_Boolean SearchOnVBounds(const SearchBoundType theSBType,
+ const Standard_Real theVzad,
+ const Standard_Real theVInit,
+ const Standard_Real theInitU2,
+ const Standard_Real theInitMainVar,
+ Standard_Real& theMainVariableValue) const;
+
+ const WorkWithBoundaries& operator=(const WorkWithBoundaries&);
+
+private:
+ friend class ComputationMethods;
+
+ const IntSurf_Quadric& myQuad1;
+ const IntSurf_Quadric& myQuad2;
+ const ComputationMethods::stCoeffsValue& myCoeffs;
+ const Bnd_Box2d& myUVSurf1;
+ const Bnd_Box2d& myUVSurf2;
+ const Standard_Integer myNbWLines;
+ const Standard_Real myPeriod;
+ const Standard_Real myTol3D;
+ const Standard_Real myTol2D;
+ const Standard_Boolean myIsReverse;
+};
+
+static void SeekAdditionalPoints(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Handle(IntSurf_LineOn2S)& theLine,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Integer theWLIndex,
+ const Standard_Integer theMinNbPoints,
+ const Standard_Integer theStartPointOnLine,
+ const Standard_Integer theEndPointOnLine,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriodOfSurf2,
+ const Standard_Boolean isTheReverse);
+
+//=======================================================================
+//function : MinMax
+//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
+// theParMAX = MAX(theParMIN, theParMAX).
+//=======================================================================
+static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
+{
+ if (theParMIN > theParMAX)
+ {
+ const Standard_Real aux = theParMAX;
+ theParMAX = theParMIN;
+ theParMIN = aux;
+ }
+}
+
+//=======================================================================
+//function : ExtremaLineLine
+//purpose : Computes extrema between the given lines. Returns parameters
+// on correspond curve (see correspond method for Extrema_ExtElC class).
+//=======================================================================
+static inline void ExtremaLineLine(const gp_Ax1& theC1,
+ const gp_Ax1& theC2,
+ const Standard_Real theCosA,
+ const Standard_Real theSqSinA,
+ Standard_Real& thePar1,
+ Standard_Real& thePar2)
+{
+ const gp_Dir &aD1 = theC1.Direction(), &aD2 = theC2.Direction();
+
+ const gp_XYZ aL1L2 = theC2.Location().XYZ() - theC1.Location().XYZ();
+ const Standard_Real aD1L = aD1.XYZ().Dot(aL1L2), aD2L = aD2.XYZ().Dot(aL1L2);
+
+ thePar1 = (aD1L - theCosA * aD2L) / theSqSinA;
+ thePar2 = (theCosA * aD1L - aD2L) / theSqSinA;
+}
+
+//=======================================================================
+//function : VBoundaryPrecise
+//purpose : By default, we shall consider, that V1 and V2 will be increased
+// if U1 is increased. But if it is not, new V1set and/or V2set
+// must be computed as [V1current - DeltaV1] (analogically
+// for V2). This function processes this case.
+//=======================================================================
+static void VBoundaryPrecise(const math_Matrix& theMatr,
+ const Standard_Real theV1AfterDecrByDelta,
+ const Standard_Real theV2AfterDecrByDelta,
+ Standard_Real& theV1Set,
+ Standard_Real& theV2Set)
+{
+ //Now we are going to define if V1 (and V2) increases
+ //(or decreases) when U1 will increase.
+ const Standard_Integer aNbDim = 3;
+ math_Matrix aSyst(1, aNbDim, 1, aNbDim);
+
+ aSyst.SetCol(1, theMatr.Col(1));
+ aSyst.SetCol(2, theMatr.Col(2));
+ aSyst.SetCol(3, theMatr.Col(4));
+
+ //We have the system (see comment to StepComputing(...) function)
+ // {a11*dV1 + a12*dV2 + a14*dU2 = -a13*dU1
+ // {a21*dV1 + a22*dV2 + a24*dU2 = -a23*dU1
+ // {a31*dV1 + a32*dV2 + a34*dU2 = -a33*dU1
+
+ const Standard_Real aDet = aSyst.Determinant();
+
+ aSyst.SetCol(1, theMatr.Col(3));
+ const Standard_Real aDet1 = aSyst.Determinant();
+
+ aSyst.SetCol(1, theMatr.Col(1));
+ aSyst.SetCol(2, theMatr.Col(3));
+
+ const Standard_Real aDet2 = aSyst.Determinant();
+
+ //Now,
+ // dV1 = -dU1*aDet1/aDet
+ // dV2 = -dU1*aDet2/aDet
+
+ //If U1 is increased then dU1 > 0.
+ //If (aDet1/aDet > 0) then dV1 < 0 and
+ //V1 will be decreased after increasing U1.
+
+ //We have analogical situation with V2-parameter.
+
+ if (aDet * aDet1 > 0.0)
+ {
+ theV1Set = theV1AfterDecrByDelta;
+ }
+
+ if (aDet * aDet2 > 0.0)
+ {
+ theV2Set = theV2AfterDecrByDelta;
+ }
+}
+
+//=======================================================================
+//function : DeltaU1Computing
+//purpose : Computes new step for U1 parameter.
+//=======================================================================
+static inline Standard_Boolean DeltaU1Computing(const math_Matrix& theSyst,
+ const math_Vector& theFree,
+ Standard_Real& theDeltaU1Found)
+{
+ Standard_Real aDet = theSyst.Determinant();
+
+ if (Abs(aDet) > aNulValue)
+ {
+ math_Matrix aSyst1(theSyst);
+ aSyst1.SetCol(2, theFree);
+
+ theDeltaU1Found = Abs(aSyst1.Determinant() / aDet);
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+//=======================================================================
+//function : StepComputing
+//purpose :
+//
+//Attention!!!:
+// theMatr must have 3*5-dimension strictly.
+// For system
+// {a11*V1+a12*V2+a13*dU1+a14*dU2=b1;
+// {a21*V1+a22*V2+a23*dU1+a24*dU2=b2;
+// {a31*V1+a32*V2+a33*dU1+a34*dU2=b3;
+// theMatr must be following:
+// (a11 a12 a13 a14 b1)
+// (a21 a22 a23 a24 b2)
+// (a31 a32 a33 a34 b3)
+//=======================================================================
+static Standard_Boolean StepComputing(const math_Matrix& theMatr,
+ const Standard_Real theV1Cur,
+ const Standard_Real theV2Cur,
+ const Standard_Real theDeltaV1,
+ const Standard_Real theDeltaV2,
+ Standard_Real& theDeltaU1Found/*,
+ Standard_Real& theDeltaU2Found,
+ Standard_Real& theV1Found,
+ Standard_Real& theV2Found*/)
+{
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ bool flShow = false;
+
+ if (flShow)
+ {
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(1, 1),
+ theMatr(1, 2),
+ theMatr(1, 3),
+ theMatr(1, 4),
+ theMatr(1, 5));
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(2, 1),
+ theMatr(2, 2),
+ theMatr(2, 3),
+ theMatr(2, 4),
+ theMatr(2, 5));
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(3, 1),
+ theMatr(3, 2),
+ theMatr(3, 3),
+ theMatr(3, 4),
+ theMatr(3, 5));
+ }
+#endif
+
+ Standard_Boolean isSuccess = Standard_False;
+ theDeltaU1Found /* = theDeltaU2Found*/ = RealLast();
+ //theV1Found = theV1set;
+ //theV2Found = theV2Set;
+ const Standard_Integer aNbDim = 3;
+
+ math_Matrix aSyst(1, aNbDim, 1, aNbDim);
+ math_Vector aFree(1, aNbDim);
+
+ //By default, increasing V1(U1) and V2(U1) functions is
+ //considered
+ Standard_Real aV1Set = theV1Cur + theDeltaV1, aV2Set = theV2Cur + theDeltaV2;
+
+ //However, what is indeed?
+ VBoundaryPrecise(theMatr, theV1Cur - theDeltaV1, theV2Cur - theDeltaV2, aV1Set, aV2Set);
+
+ aSyst.SetCol(2, theMatr.Col(3));
+ aSyst.SetCol(3, theMatr.Col(4));
+
+ for (Standard_Integer i = 0; i < 2; i++)
+ {
+ if (i == 0)
+ { //V1 is known
+ aSyst.SetCol(1, theMatr.Col(2));
+ aFree.Set(1, aNbDim, theMatr.Col(5) - aV1Set * theMatr.Col(1));
+ }
+ else
+ { //i==1 => V2 is known
+ aSyst.SetCol(1, theMatr.Col(1));
+ aFree.Set(1, aNbDim, theMatr.Col(5) - aV2Set * theMatr.Col(2));
+ }
+
+ Standard_Real aNewDU = theDeltaU1Found;
+ if (DeltaU1Computing(aSyst, aFree, aNewDU))
+ {
+ isSuccess = Standard_True;
+ if (aNewDU < theDeltaU1Found)
+ {
+ theDeltaU1Found = aNewDU;
+ }
+ }
+ }
+
+ if (!isSuccess)
+ {
+ aFree = theMatr.Col(5) - aV1Set * theMatr.Col(1) - aV2Set * theMatr.Col(2);
+ math_Matrix aSyst1(1, aNbDim, 1, 2);
+ aSyst1.SetCol(1, aSyst.Col(2));
+ aSyst1.SetCol(2, aSyst.Col(3));
+
+ //Now we have overdetermined system.
+
+ const Standard_Real aDet1 = theMatr(1, 3) * theMatr(2, 4) - theMatr(2, 3) * theMatr(1, 4);
+ const Standard_Real aDet2 = theMatr(1, 3) * theMatr(3, 4) - theMatr(3, 3) * theMatr(1, 4);
+ const Standard_Real aDet3 = theMatr(2, 3) * theMatr(3, 4) - theMatr(3, 3) * theMatr(2, 4);
+ const Standard_Real anAbsD1 = Abs(aDet1);
+ const Standard_Real anAbsD2 = Abs(aDet2);
+ const Standard_Real anAbsD3 = Abs(aDet3);
+
+ if (anAbsD1 >= anAbsD2)
+ {
+ if (anAbsD1 >= anAbsD3)
+ {
+ //Det1
+ if (anAbsD1 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(1) * theMatr(2, 4) - aFree(2) * theMatr(1, 4)) / anAbsD1;
+ isSuccess = Standard_True;
+ }
+ else
+ {
+ //Det3
+ if (anAbsD3 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(2) * theMatr(3, 4) - aFree(3) * theMatr(2, 4)) / anAbsD3;
+ isSuccess = Standard_True;
+ }
+ }
+ else
+ {
+ if (anAbsD2 >= anAbsD3)
+ {
+ //Det2
+ if (anAbsD2 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(1) * theMatr(3, 4) - aFree(3) * theMatr(1, 4)) / anAbsD2;
+ isSuccess = Standard_True;
+ }
+ else
+ {
+ //Det3
+ if (anAbsD3 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(2) * theMatr(3, 4) - aFree(3) * theMatr(2, 4)) / anAbsD3;
+ isSuccess = Standard_True;
+ }
+ }
+ }
+
+ return isSuccess;
+}
+
+//=======================================================================
+//function : ProcessBounds
+//purpose :
+//=======================================================================
+void ProcessBounds(const Handle(IntPatch_ALine)& alig, //-- ligne courante
+ const IntPatch_SequenceOfLine& slin,
+ const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ Standard_Boolean& procf,
+ const gp_Pnt& ptf, //-- Debut Ligne Courante
+ const Standard_Real first, //-- Paramf
+ Standard_Boolean& procl,
+ const gp_Pnt& ptl, //-- Fin Ligne courante
+ const Standard_Real last, //-- Paraml
+ Standard_Boolean& Multpoint,
+ const Standard_Real Tol)
+{
+ Standard_Integer j, k;
+ Standard_Real U1, V1, U2, V2;
+ IntPatch_Point ptsol;
+ Standard_Real d;
+
+ if (procf && procl)
+ {
+ j = slin.Length() + 1;
+ }
+ else
+ {
+ j = 1;
+ }
+
+ //-- On prend les lignes deja enregistrees
+
+ while (j <= slin.Length())
+ {
+ if (slin.Value(j)->ArcType() == IntPatch_Analytic)
+ {
+ const Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(j));
+ k = 1;
+
+ //-- On prend les vertex des lignes deja enregistrees
+
+ while (k <= aligold->NbVertex())
+ {
+ ptsol = aligold->Vertex(k);
+ if (!procf)
+ {
+ d = ptf.Distance(ptsol.Value());
+ if (d <= Tol)
+ {
+ ptsol.SetTolerance(Tol);
+ if (!ptsol.IsMultiple())
+ {
+ //-- le point ptsol (de aligold) est declare multiple sur aligold
+ Multpoint = Standard_True;
+ ptsol.SetMultiple(Standard_True);
+ aligold->Replace(k, ptsol);
+ }
+ ptsol.SetParameter(first);
+ alig->AddVertex(ptsol);
+ alig->SetFirstPoint(alig->NbVertex());
+ procf = Standard_True;
+
+ //-- On restore le point avec son parametre sur aligold
+ ptsol = aligold->Vertex(k);
+ }
+ }
+ if (!procl)
+ {
+ if (ptl.Distance(ptsol.Value()) <= Tol)
+ {
+ ptsol.SetTolerance(Tol);
+ if (!ptsol.IsMultiple())
+ {
+ Multpoint = Standard_True;
+ ptsol.SetMultiple(Standard_True);
+ aligold->Replace(k, ptsol);
+ }
+ ptsol.SetParameter(last);
+ alig->AddVertex(ptsol);
+ alig->SetLastPoint(alig->NbVertex());
+ procl = Standard_True;
+
+ //-- On restore le point avec son parametre sur aligold
+ ptsol = aligold->Vertex(k);
+ }
+ }
+ if (procf && procl)
+ {
+ k = aligold->NbVertex() + 1;
+ }
+ else
+ {
+ k = k + 1;
+ }
+ }
+ if (procf && procl)
+ {
+ j = slin.Length() + 1;
+ }
+ else
+ {
+ j = j + 1;
+ }
+ }
+ }
+
+ ptsol.SetTolerance(Tol);
+ if (!procf && !procl)
+ {
+ Quad1.Parameters(ptf, U1, V1);
+ Quad2.Parameters(ptf, U2, V2);
+ ptsol.SetValue(ptf, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(first);
+ if (ptf.Distance(ptl) <= Tol)
+ {
+ ptsol.SetMultiple(Standard_True); // a voir
+ Multpoint = Standard_True; // a voir de meme
+ alig->AddVertex(ptsol);
+ alig->SetFirstPoint(alig->NbVertex());
+
+ ptsol.SetParameter(last);
+ alig->AddVertex(ptsol);
+ alig->SetLastPoint(alig->NbVertex());
+ }
+ else
+ {
+ alig->AddVertex(ptsol);
+ alig->SetFirstPoint(alig->NbVertex());
+ Quad1.Parameters(ptl, U1, V1);
+ Quad2.Parameters(ptl, U2, V2);
+ ptsol.SetValue(ptl, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(last);
+ alig->AddVertex(ptsol);
+ alig->SetLastPoint(alig->NbVertex());
+ }
+ }
+ else if (!procf)
+ {
+ Quad1.Parameters(ptf, U1, V1);
+ Quad2.Parameters(ptf, U2, V2);
+ ptsol.SetValue(ptf, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(first);
+ alig->AddVertex(ptsol);
+ alig->SetFirstPoint(alig->NbVertex());
+ }
+ else if (!procl)
+ {
+ Quad1.Parameters(ptl, U1, V1);
+ Quad2.Parameters(ptl, U2, V2);
+ ptsol.SetValue(ptl, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ ptsol.SetParameter(last);
+ alig->AddVertex(ptsol);
+ alig->SetLastPoint(alig->NbVertex());
+ }
+}
+
+//=======================================================================
+//function : CyCyAnalyticalIntersect
+//purpose : Checks if intersection curve is analytical (line, circle, ellipse)
+// and returns these curves.
+//=======================================================================
+Standard_Boolean CyCyAnalyticalIntersect(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const IntAna_QuadQuadGeo& theInter,
+ const Standard_Real Tol,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Same,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+{
+ IntPatch_Point ptsol;
+
+ Standard_Integer i;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+
+ gp_Elips elipsol;
+ gp_Lin linsol;
+
+ gp_Cylinder Cy1(Quad1.Cylinder());
+ gp_Cylinder Cy2(Quad2.Cylinder());
+
+ typint = theInter.TypeInter();
+ Standard_Integer NbSol = theInter.NbSolutions();
+ Empty = Standard_False;
+ Same = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Same:
+ {
+ Same = Standard_True;
+ }
+ break;
+
+ case IntAna_Point:
+ {
+ gp_Pnt psol(theInter.Point(1));
+ ptsol.SetValue(psol, Tol, Standard_True);
+
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+
+ case IntAna_Line:
+ {
+ gp_Pnt ptref;
+ if (NbSol == 1)
+ { // Cylinders are tangent to each other by line
+ linsol = theInter.Line(1);
+ ptref = linsol.Location();
+
+ //Radius-vectors
+ gp_Dir crb1(gp_Vec(ptref, Cy1.Location()));
+ gp_Dir crb2(gp_Vec(ptref, Cy2.Location()));
+
+ //outer normal lines
+ gp_Vec norm1(Quad1.Normale(ptref));
+ gp_Vec norm2(Quad2.Normale(ptref));
+ IntSurf_Situation situcyl1;
+ IntSurf_Situation situcyl2;
+
+ if (crb1.Dot(crb2) < 0.)
+ { // centre de courbures "opposes"
+ //ATTENTION!!!
+ // Normal and Radius-vector of the 1st(!) cylinder
+ // is used for judging what the situation of the 2nd(!)
+ // cylinder is.
+
+ if (norm1.Dot(crb1) > 0.)
+ {
+ situcyl2 = IntSurf_Inside;
+ }
+ else
+ {
+ situcyl2 = IntSurf_Outside;
+ }
+
+ if (norm2.Dot(crb2) > 0.)
+ {
+ situcyl1 = IntSurf_Inside;
+ }
+ else
+ {
+ situcyl1 = IntSurf_Outside;
+ }
+ }
+ else
+ {
+ if (Cy1.Radius() < Cy2.Radius())
+ {
+ if (norm1.Dot(crb1) > 0.)
+ {
+ situcyl2 = IntSurf_Inside;
+ }
+ else
+ {
+ situcyl2 = IntSurf_Outside;
+ }
+
+ if (norm2.Dot(crb2) > 0.)
+ {
+ situcyl1 = IntSurf_Outside;
+ }
+ else
+ {
+ situcyl1 = IntSurf_Inside;
+ }
+ }
+ else
+ {
+ if (norm1.Dot(crb1) > 0.)
+ {
+ situcyl2 = IntSurf_Outside;
+ }
+ else
+ {
+ situcyl2 = IntSurf_Inside;
+ }
+
+ if (norm2.Dot(crb2) > 0.)
+ {
+ situcyl1 = IntSurf_Inside;
+ }
+ else
+ {
+ situcyl1 = IntSurf_Outside;
+ }
+ }
+ }
+
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_True, situcyl1, situcyl2);
+ slin.Append(glig);
+ }
+ else
+ {
+ for (i = 1; i <= NbSol; i++)
+ {
+ linsol = theInter.Line(i);
+ ptref = linsol.Location();
+ gp_Vec lsd = linsol.Direction();
+
+ //Theoretically, qwe = +/- 1.0.
+ Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ }
+ }
+ break;
+
+ case IntAna_Ellipse:
+ {
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ IntPatch_Point pmult1, pmult2;
+
+ elipsol = theInter.Ellipse(1);
+
+ gp_Pnt pttang1(ElCLib::Value(0.5 * M_PI, elipsol));
+ gp_Pnt pttang2(ElCLib::Value(1.5 * M_PI, elipsol));
+
+ Multpoint = Standard_True;
+ pmult1.SetValue(pttang1, Tol, Standard_True);
+ pmult2.SetValue(pttang2, Tol, Standard_True);
+ pmult1.SetMultiple(Standard_True);
+ pmult2.SetMultiple(Standard_True);
+
+ Standard_Real oU1, oV1, oU2, oV2;
+ Quad1.Parameters(pttang1, oU1, oV1);
+ Quad2.Parameters(pttang1, oU2, oV2);
+
+ pmult1.SetParameters(oU1, oV1, oU2, oV2);
+ Quad1.Parameters(pttang2, oU1, oV1);
+ Quad2.Parameters(pttang2, oU2, oV2);
+
+ pmult2.SetParameters(oU1, oV1, oU2, oV2);
+
+ // on traite la premiere ellipse
+
+ //-- Calcul de la Transition de la ligne
+ ElCLib::D1(0., elipsol, ptref, Tgt);
+
+ //Theoretically, qwe = +/- |Tgt|.
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+
+ //-- Transition calculee au point 0 -> Trans2 , Trans1
+ //-- car ici, on devarit calculer en PI
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol, Standard_False, trans2, trans1);
+ //
+ {
+ Standard_Real aU1, aV1, aU2, aV2;
+ IntPatch_Point aIP;
+ gp_Pnt aP(ElCLib::Value(0., elipsol));
+ //
+ aIP.SetValue(aP, Tol, Standard_False);
+ aIP.SetMultiple(Standard_False);
+ //
+ Quad1.Parameters(aP, aU1, aV1);
+ Quad2.Parameters(aP, aU2, aV2);
+
+ aIP.SetParameters(aU1, aV1, aU2, aV2);
+ //
+ aIP.SetParameter(0.);
+ glig->AddVertex(aIP);
+ glig->SetFirstPoint(1);
+ //
+ aIP.SetParameter(2. * M_PI);
+ glig->AddVertex(aIP);
+ glig->SetLastPoint(2);
+ }
+ //
+ pmult1.SetParameter(0.5 * M_PI);
+ glig->AddVertex(pmult1);
+ //
+ pmult2.SetParameter(1.5 * M_PI);
+ glig->AddVertex(pmult2);
+
+ //
+ slin.Append(glig);
+
+ //-- Transitions calculee au point 0 OK
+ //
+ // on traite la deuxieme ellipse
+ elipsol = theInter.Ellipse(2);
+
+ Standard_Real param1 = ElCLib::Parameter(elipsol, pttang1);
+ Standard_Real param2 = ElCLib::Parameter(elipsol, pttang2);
+ Standard_Real parampourtransition = 0.0;
+ if (param1 < param2)
+ {
+ pmult1.SetParameter(0.5 * M_PI);
+ pmult2.SetParameter(1.5 * M_PI);
+ parampourtransition = M_PI;
+ }
+ else
+ {
+ pmult1.SetParameter(1.5 * M_PI);
+ pmult2.SetParameter(0.5 * M_PI);
+ parampourtransition = 0.0;
+ }
+
+ //-- Calcul des transitions de ligne pour la premiere ligne
+ ElCLib::D1(parampourtransition, elipsol, ptref, Tgt);
+
+ //Theoretically, qwe = +/- |Tgt|.
+ qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+
+ //-- La transition a ete calculee sur un point de cette ligne
+ glig = new IntPatch_GLine(elipsol, Standard_False, trans1, trans2);
+ //
+ {
+ Standard_Real aU1, aV1, aU2, aV2;
+ IntPatch_Point aIP;
+ gp_Pnt aP(ElCLib::Value(0., elipsol));
+ //
+ aIP.SetValue(aP, Tol, Standard_False);
+ aIP.SetMultiple(Standard_False);
+ //
+
+ Quad1.Parameters(aP, aU1, aV1);
+ Quad2.Parameters(aP, aU2, aV2);
+
+ aIP.SetParameters(aU1, aV1, aU2, aV2);
+ //
+ aIP.SetParameter(0.);
+ glig->AddVertex(aIP);
+ glig->SetFirstPoint(1);
+ //
+ aIP.SetParameter(2. * M_PI);
+ glig->AddVertex(aIP);
+ glig->SetLastPoint(2);
+ }
+ //
+ glig->AddVertex(pmult1);
+ glig->AddVertex(pmult2);
+ //
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_Parabola:
+ case IntAna_Hyperbola: throw Standard_Failure("IntCyCy(): Wrong intersection type!");
+
+ case IntAna_Circle:
+ // Circle is useful when we will work with trimmed surfaces
+ // (two cylinders can be tangent by their basises, e.g. circle)
+ case IntAna_NoGeometricSolution:
+ default: return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : ShortCosForm
+//purpose : Represents theCosFactor*cosA+theSinFactor*sinA as
+// theCoeff*cos(A-theAngle) if it is possibly (all angles are
+// in radians).
+//=======================================================================
+static void ShortCosForm(const Standard_Real theCosFactor,
+ const Standard_Real theSinFactor,
+ Standard_Real& theCoeff,
+ Standard_Real& theAngle)
+{
+ theCoeff = sqrt(theCosFactor * theCosFactor + theSinFactor * theSinFactor);
+ theAngle = 0.0;
+ if (IsEqual(theCoeff, 0.0))
+ {
+ theAngle = 0.0;
+ return;
+ }
+
+ theAngle = acos(Abs(theCosFactor / theCoeff));
+
+ if (theSinFactor > 0.0)
+ {
+ if (IsEqual(theCosFactor, 0.0))
+ {
+ theAngle = M_PI / 2.0;
+ }
+ else if (theCosFactor < 0.0)
+ {
+ theAngle = M_PI - theAngle;
+ }
+ }
+ else if (IsEqual(theSinFactor, 0.0))
+ {
+ if (theCosFactor < 0.0)
+ {
+ theAngle = M_PI;
+ }
+ }
+ if (theSinFactor < 0.0)
+ {
+ if (theCosFactor > 0.0)
+ {
+ theAngle = 2.0 * M_PI - theAngle;
+ }
+ else if (IsEqual(theCosFactor, 0.0))
+ {
+ theAngle = 3.0 * M_PI / 2.0;
+ }
+ else if (theCosFactor < 0.0)
+ {
+ theAngle = M_PI + theAngle;
+ }
+ }
+}
+
+//=======================================================================
+//function : CylCylMonotonicity
+//purpose : Determines, if U2(U1) function is increasing.
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylMonotonicity(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Standard_Boolean& theIsIncreasing)
+{
+ // U2(U1) = FI2 + (+/-)acos(B*cos(U1 - FI1) + C);
+ //Accordingly,
+ //Func. U2(X1) = FI2 + X1;
+ //Func. X1(X2) = anArccosFactor*X2;
+ //Func. X2(X3) = acos(X3);
+ //Func. X3(X4) = B*X4 + C;
+ //Func. X4(U1) = cos(U1 - FI1).
+ //
+ //Consequently,
+ //U2(X1) is always increasing.
+ //X1(X2) is increasing if anArccosFactor > 0.0 and
+ //is decreasing otherwise.
+ //X2(X3) is always decreasing.
+ //Therefore, U2(X3) is decreasing if anArccosFactor > 0.0 and
+ //is increasing otherwise.
+ //X3(X4) is increasing if B > 0 and is decreasing otherwise.
+ //X4(U1) is increasing if U1 - FI1 in [PI, 2*PI) and
+ //is decreasing U1 - FI1 in [0, PI) or if (U1 - FI1 == 2PI).
+ //After that, we can predict behaviour of U2(U1) function:
+ //if it is increasing or decreasing.
+
+ //For "+/-" sign. If isPlus == TRUE, "+" is chosen, otherwise, we choose "-".
+ Standard_Boolean isPlus = Standard_False;
+
+ switch (theWLIndex)
+ {
+ case 0: isPlus = Standard_True; break;
+ case 1: isPlus = Standard_False; break;
+ default:
+ //throw Standard_Failure("Error. Range Error!!!!");
+ return Standard_False;
+ }
+
+ Standard_Real aU1Temp = theU1par - theCoeffs.mFI1;
+ InscribePoint(0, thePeriod, aU1Temp, 0.0, thePeriod, Standard_False);
+
+ theIsIncreasing = Standard_True;
+
+ if (((M_PI - aU1Temp) < RealSmall()) && (aU1Temp < thePeriod))
+ {
+ theIsIncreasing = Standard_False;
+ }
+
+ if (theCoeffs.mB < 0.0)
+ {
+ theIsIncreasing = !theIsIncreasing;
+ }
+
+ if (!isPlus)
+ {
+ theIsIncreasing = !theIsIncreasing;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CylCylComputeParameters
+//purpose : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
+// estimates the tolerance of U2-computing (estimation result is
+// assigned to *theDelta value).
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real* const theDelta)
+{
+ //This formula is got from some experience and can be changed.
+ const Standard_Real aTol0 = Min(10.0 * Epsilon(1.0) * theCoeffs.mB, aNulValue);
+ const Standard_Real aTol = 1.0 - aTol0;
+
+ if (theWLIndex < 0 || theWLIndex > 1)
+ return Standard_False;
+
+ const Standard_Real aSign = theWLIndex ? -1.0 : 1.0;
+
+ Standard_Real anArg = cos(theU1par - theCoeffs.mFI1);
+ anArg = theCoeffs.mB * anArg + theCoeffs.mC;
+
+ if (anArg >= aTol)
+ {
+ if (theDelta)
+ *theDelta = 0.0;
+
+ anArg = 1.0;
+ }
+ else if (anArg <= -aTol)
+ {
+ if (theDelta)
+ *theDelta = 0.0;
+
+ anArg = -1.0;
+ }
+ else if (theDelta)
+ {
+ //There is a case, when
+ // const double aPar = 0.99999999999721167;
+ // const double aFI2 = 2.3593296083566181e-006;
+
+ //Then
+ // aPar - cos(aFI2) == -5.10703e-015 ==> cos(aFI2) == aPar.
+ //Theoretically, in this case
+ // aFI2 == +/- acos(aPar).
+ //However,
+ // acos(aPar) - aFI2 == 2.16362e-009.
+ //Error is quite big.
+
+ //This error should be estimated. Let use following way, which is based
+ //on expanding to Taylor series.
+
+ // acos(p)-acos(p+x) = x/sqrt(1-p*p).
+
+ //If p == (1-d) (when p > 0) or p == (-1+d) (when p < 0) then
+ // acos(p)-acos(p+x) = x/sqrt(d*(2-d)).
+
+ //Here always aTol0 <= d <= 1. Max(x) is considered (!) to be equal to aTol0.
+ //In this case
+ // 8*aTol0 <= acos(p)-acos(p+x) <= sqrt(2/(2-aTol0)-1),
+ // because 0 < aTol0 < 1.
+ //E.g. when aTol0 = 1.0e-11,
+ // 8.0e-11 <= acos(p)-acos(p+x) < 2.24e-6.
+
+ const Standard_Real aDelta = Min(1.0 - anArg, 1.0 + anArg);
+ Standard_DivideByZero_Raise_if((aDelta * aDelta < RealSmall()) || (aDelta >= 2.0),
+ "IntPatch_ImpImpIntersection_4.gxx, CylCylComputeParameters()");
+ *theDelta = aTol0 / sqrt(aDelta * (2.0 - aDelta));
+ }
+
+ theU2 = acos(anArg);
+ theU2 = theCoeffs.mFI2 + aSign * theU2;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CylCylComputeParameters
+//purpose : Computes V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively).
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1,
+ const Standard_Real theU2,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theV1,
+ Standard_Real& theV2)
+{
+ theV1 = theCoeffs.mK21 * sin(theU2) + theCoeffs.mK11 * sin(theU1) + theCoeffs.mL21 * cos(theU2) + theCoeffs.mL11 * cos(theU1)
+ + theCoeffs.mM1;
+
+ theV2 = theCoeffs.mK22 * sin(theU2) + theCoeffs.mK12 * sin(theU1) + theCoeffs.mL22 * cos(theU2) + theCoeffs.mL12 * cos(theU1)
+ + theCoeffs.mM2;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CylCylComputeParameters
+//purpose : Computes U2 (U-parameter of the 2nd cylinder),
+// V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively).
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real& theV1,
+ Standard_Real& theV2)
+{
+ if (!CylCylComputeParameters(theU1par, theWLIndex, theCoeffs, theU2))
+ return Standard_False;
+
+ if (!CylCylComputeParameters(theU1par, theU2, theCoeffs, theV1, theV2))
+ return Standard_False;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : SearchOnVBounds
+//purpose :
+//=======================================================================
+Standard_Boolean WorkWithBoundaries::SearchOnVBounds(const SearchBoundType theSBType,
+ const Standard_Real theVzad,
+ const Standard_Real theVInit,
+ const Standard_Real theInitU2,
+ const Standard_Real theInitMainVar,
+ Standard_Real& theMainVariableValue) const
+{
+ const Standard_Integer aNbDim = 3;
+ const Standard_Real aMaxError = 4.0 * M_PI; // two periods
+
+ theMainVariableValue = theInitMainVar;
+ const Standard_Real aTol2 = 1.0e-18;
+ Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVInit;
+
+ //Structure of aMatr:
+ // C_{1}*U_{1} & C_{2}*U_{2} & C_{3}*V_{*},
+ //where C_{1}, C_{2} and C_{3} are math_Vector.
+ math_Matrix aMatr(1, aNbDim, 1, aNbDim);
+
+ Standard_Real anError = RealLast();
+ Standard_Real anErrorPrev = anError;
+ Standard_Integer aNbIter = 0;
+ do
+ {
+ if (++aNbIter > 1000)
+ return Standard_False;
+
+ const Standard_Real aSinU1 = sin(aMainVarPrev), aCosU1 = cos(aMainVarPrev), aSinU2 = sin(aU2Prev), aCosU2 = cos(aU2Prev);
+
+ math_Vector aVecFreeMem = (myCoeffs.mVecA2 * aU2Prev + myCoeffs.mVecB2) * aSinU2
+ - (myCoeffs.mVecB2 * aU2Prev - myCoeffs.mVecA2) * aCosU2
+ + (myCoeffs.mVecA1 * aMainVarPrev + myCoeffs.mVecB1) * aSinU1
+ - (myCoeffs.mVecB1 * aMainVarPrev - myCoeffs.mVecA1) * aCosU1 + myCoeffs.mVecD;
+
+ math_Vector aMSum(1, 3);
+
+ switch (theSBType)
+ {
+ case SearchV1:
+ aMatr.SetCol(3, myCoeffs.mVecC2);
+ aMSum = myCoeffs.mVecC1 * theVzad;
+ aVecFreeMem -= aMSum;
+ aMSum += myCoeffs.mVecC2 * anOtherVar;
+ break;
+
+ case SearchV2:
+ aMatr.SetCol(3, myCoeffs.mVecC1);
+ aMSum = myCoeffs.mVecC2 * theVzad;
+ aVecFreeMem -= aMSum;
+ aMSum += myCoeffs.mVecC1 * anOtherVar;
+ break;
+
+ default: return Standard_False;
+ }
+
+ aMatr.SetCol(1, myCoeffs.mVecA1 * aSinU1 - myCoeffs.mVecB1 * aCosU1);
+ aMatr.SetCol(2, myCoeffs.mVecA2 * aSinU2 - myCoeffs.mVecB2 * aCosU2);
+
+ Standard_Real aDetMainSyst = aMatr.Determinant();
+
+ if (Abs(aDetMainSyst) < aNulValue)
+ {
+ return Standard_False;
+ }
+
+ math_Matrix aM1(aMatr), aM2(aMatr), aM3(aMatr);
+ aM1.SetCol(1, aVecFreeMem);
+ aM2.SetCol(2, aVecFreeMem);
+ aM3.SetCol(3, aVecFreeMem);
+
+ const Standard_Real aDetMainVar = aM1.Determinant();
+ const Standard_Real aDetVar1 = aM2.Determinant();
+ const Standard_Real aDetVar2 = aM3.Determinant();
+
+ Standard_Real aDelta = aDetMainVar / aDetMainSyst - aMainVarPrev;
+
+ if (Abs(aDelta) > aMaxError)
+ return Standard_False;
+
+ anError = aDelta * aDelta;
+ aMainVarPrev += aDelta;
+
+ ///
+ aDelta = aDetVar1 / aDetMainSyst - aU2Prev;
+
+ if (Abs(aDelta) > aMaxError)
+ return Standard_False;
+
+ anError += aDelta * aDelta;
+ aU2Prev += aDelta;
+
+ ///
+ aDelta = aDetVar2 / aDetMainSyst - anOtherVar;
+ anError += aDelta * aDelta;
+ anOtherVar += aDelta;
+
+ if (anError > anErrorPrev)
+ { //Method diverges. Keep the best result
+ const Standard_Real aSinU1Last = sin(aMainVarPrev), aCosU1Last = cos(aMainVarPrev), aSinU2Last = sin(aU2Prev),
+ aCosU2Last = cos(aU2Prev);
+ aMSum -= (myCoeffs.mVecA1 * aCosU1Last + myCoeffs.mVecB1 * aSinU1Last + myCoeffs.mVecA2 * aCosU2Last
+ + myCoeffs.mVecB2 * aSinU2Last + myCoeffs.mVecD);
+ const Standard_Real aSQNorm = aMSum.Norm2();
+ return (aSQNorm < aTol2);
+ }
+ else
+ {
+ theMainVariableValue = aMainVarPrev;
+ }
+
+ anErrorPrev = anError;
+ } while (anError > aTol2);
+
+ theMainVariableValue = aMainVarPrev;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : InscribePoint
+//purpose : If theFlForce==TRUE theUGiven will be changed forcefully
+// even if theUGiven is already inscibed in the boundary
+// (if it is possible; i.e. if new theUGiven is inscribed
+// in the boundary, too).
+//=======================================================================
+Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
+ const Standard_Real theUlTarget,
+ Standard_Real& theUGiven,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriod,
+ const Standard_Boolean theFlForce)
+{
+ if (Precision::IsInfinite(theUGiven))
+ {
+ return Standard_False;
+ }
+
+ if ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D))
+ { //it has already inscribed
+
+ /*
+ Utf U Utl
+ + * +
+ */
+
+ if (theFlForce)
+ {
+ Standard_Real anUtemp = theUGiven + thePeriod;
+ if ((theUfTarget - anUtemp <= theTol2D) && (anUtemp - theUlTarget <= theTol2D))
+ {
+ theUGiven = anUtemp;
+ return Standard_True;
+ }
+
+ anUtemp = theUGiven - thePeriod;
+ if ((theUfTarget - anUtemp <= theTol2D) && (anUtemp - theUlTarget <= theTol2D))
+ {
+ theUGiven = anUtemp;
+ }
+ }
+
+ return Standard_True;
+ }
+
+ const Standard_Real aUf = theUfTarget - theTol2D;
+ const Standard_Real aUl = aUf + thePeriod;
+
+ theUGiven = ElCLib::InPeriod(theUGiven, aUf, aUl);
+
+ return ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D));
+}
+
+//=======================================================================
+//function : InscribeInterval
+//purpose : Shifts theRange in order to make at least one of its
+// boundary in the range [theUfTarget, theUlTarget]
+//=======================================================================
+static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
+ const Standard_Real theUlTarget,
+ Bnd_Range& theRange,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriod)
+{
+ Standard_Real anUpar = 0.0;
+ if (!theRange.GetMin(anUpar))
+ {
+ return Standard_False;
+ }
+
+ const Standard_Real aDelta = theRange.Delta();
+ if (InscribePoint(theUfTarget, theUlTarget, anUpar, theTol2D, thePeriod, (Abs(theUlTarget - anUpar) < theTol2D)))
+ {
+ theRange.SetVoid();
+ theRange.Add(anUpar);
+ theRange.Add(anUpar + aDelta);
+ }
+ else
+ {
+ if (!theRange.GetMax(anUpar))
+ {
+ return Standard_False;
+ }
+
+ if (InscribePoint(theUfTarget, theUlTarget, anUpar, theTol2D, thePeriod, (Abs(theUfTarget - anUpar) < theTol2D)))
+ {
+ theRange.SetVoid();
+ theRange.Add(anUpar);
+ theRange.Add(anUpar - aDelta);
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : ExcludeNearElements
+//purpose : Checks if theArr contains two almost equal elements.
+// If it is true then one of equal elements will be excluded
+// (made infinite).
+// Returns TRUE if at least one element of theArr has been changed.
+//ATTENTION!!!
+// 1. Every not infinite element of theArr is considered to be
+// in [0, T] interval (where T is the period);
+// 2. theArr must be sorted in ascending order.
+//=======================================================================
+static Standard_Boolean ExcludeNearElements(Standard_Real theArr[],
+ const Standard_Integer theNOfMembers,
+ const Standard_Real theUSurf1f,
+ const Standard_Real theUSurf1l,
+ const Standard_Real theTol)
+{
+ Standard_Boolean aRetVal = Standard_False;
+ for (Standard_Integer i = 1; i < theNOfMembers; i++)
+ {
+ Standard_Real &anA = theArr[i], &anB = theArr[i - 1];
+
+ //Here, anA >= anB
+
+ if (Precision::IsInfinite(anA))
+ break;
+
+ if ((anA - anB) < theTol)
+ {
+ if ((anB != 0.0) && (anB != theUSurf1f) && (anB != theUSurf1l))
+ anA = (anA + anB) / 2.0;
+ else
+ anA = anB;
+
+ //Make this element infinite an forget it
+ //(we will not use it in next iterations).
+ anB = Precision::Infinite();
+ aRetVal = Standard_True;
+ }
+ }
+
+ return aRetVal;
+}
+
+//=======================================================================
+//function : AddPointIntoWL
+//purpose : Surf1 is a surface, whose U-par is variable.
+// If theFlBefore == TRUE then we enable the U1-parameter
+// of the added point to be less than U1-parameter of
+// previously added point (in general U1-parameter is
+// always increased; therefore, this situation is abnormal).
+// If theOnlyCheck==TRUE then no point will be added to theLine.
+//=======================================================================
+static Standard_Boolean AddPointIntoWL(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Boolean isTheReverse,
+ const Standard_Boolean isThePrecise,
+ const gp_Pnt2d& thePntOnSurf1,
+ const gp_Pnt2d& thePntOnSurf2,
+ const Standard_Real theUfSurf1,
+ const Standard_Real theUlSurf1,
+ const Standard_Real theUfSurf2,
+ const Standard_Real theUlSurf2,
+ const Standard_Real theVfSurf1,
+ const Standard_Real theVlSurf1,
+ const Standard_Real theVfSurf2,
+ const Standard_Real theVlSurf2,
+ const Standard_Real thePeriodOfSurf1,
+ const Handle(IntSurf_LineOn2S)& theLine,
+ const Standard_Integer theWLIndex,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Standard_Boolean theFlBefore = Standard_False,
+ const Standard_Boolean theOnlyCheck = Standard_False)
+{
+ //Check if the point is in the domain or can be inscribed in the domain after adjusting.
+
+ gp_Pnt aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())), aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
+
+ Standard_Real aU1par = thePntOnSurf1.X();
+
+ // aU1par always increases. Therefore, we must reduce its
+ // value in order to continue creation of WLine.
+ if (!InscribePoint(theUfSurf1, theUlSurf1, aU1par, theTol2D, thePeriodOfSurf1, aU1par > 0.5 * (theUfSurf1 + theUlSurf1)))
+ return Standard_False;
+
+ if ((theLine->NbPoints() > 0) && ((theUlSurf1 - theUfSurf1) >= (thePeriodOfSurf1 - theTol2D))
+ && (((aU1par + thePeriodOfSurf1 - theUlSurf1) <= theTol2D) || ((aU1par - thePeriodOfSurf1 - theUfSurf1) >= theTol2D)))
+ {
+ // aU1par can be adjusted to both theUlSurf1 and theUfSurf1
+ // with equal possibilities. This code fragment allows choosing
+ // correct parameter from these two variants.
+
+ Standard_Real aU1 = 0.0, aV1 = 0.0;
+ if (isTheReverse)
+ {
+ theLine->Value(theLine->NbPoints()).ParametersOnS2(aU1, aV1);
+ }
+ else
+ {
+ theLine->Value(theLine->NbPoints()).ParametersOnS1(aU1, aV1);
+ }
+
+ const Standard_Real aDelta = aU1 - aU1par;
+ if (2.0 * Abs(aDelta) > thePeriodOfSurf1)
+ {
+ aU1par += Sign(thePeriodOfSurf1, aDelta);
+ }
+ }
+
+ Standard_Real aU2par = thePntOnSurf2.X();
+ if (!InscribePoint(theUfSurf2, theUlSurf2, aU2par, theTol2D, thePeriodOfSurf1, Standard_False))
+ return Standard_False;
+
+ Standard_Real aV1par = thePntOnSurf1.Y();
+ if ((aV1par - theVlSurf1 > theTol2D) || (theVfSurf1 - aV1par > theTol2D))
+ return Standard_False;
+
+ Standard_Real aV2par = thePntOnSurf2.Y();
+ if ((aV2par - theVlSurf2 > theTol2D) || (theVfSurf2 - aV2par > theTol2D))
+ return Standard_False;
+
+ //Get intersection point and add it in the WL
+ IntSurf_PntOn2S aPnt;
+
+ if (isTheReverse)
+ {
+ aPnt.SetValue((aPt1.XYZ() + aPt2.XYZ()) / 2.0, aU2par, aV2par, aU1par, aV1par);
+ }
+ else
+ {
+ aPnt.SetValue((aPt1.XYZ() + aPt2.XYZ()) / 2.0, aU1par, aV1par, aU2par, aV2par);
+ }
+
+ Standard_Integer aNbPnts = theLine->NbPoints();
+ if (aNbPnts > 0)
+ {
+ Standard_Real aUl = 0.0, aVl = 0.0;
+ const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
+ if (isTheReverse)
+ aPlast.ParametersOnS2(aUl, aVl);
+ else
+ aPlast.ParametersOnS1(aUl, aVl);
+
+ if (!theFlBefore && (aU1par <= aUl))
+ {
+ //Parameter value must be increased if theFlBefore == FALSE.
+
+ aU1par += thePeriodOfSurf1;
+
+ //The condition is as same as in
+ //InscribePoint(...) function
+ if ((theUfSurf1 - aU1par > theTol2D) || (aU1par - theUlSurf1 > theTol2D))
+ {
+ //New aU1par is out of target interval.
+ //Go back to old value.
+
+ return Standard_False;
+ }
+ }
+
+ if (theOnlyCheck)
+ return Standard_True;
+
+ //theTol2D is minimal step along parameter changed.
+ //Therefore, if we apply this minimal step two
+ //neighbour points will be always "same". Consequently,
+ //we should reduce tolerance for IsSame checking.
+ const Standard_Real aDTol = 1.0 - Epsilon(1.0);
+ if (aPnt.IsSame(aPlast, theTol3D * aDTol, theTol2D * aDTol))
+ {
+ theLine->RemovePoint(aNbPnts);
+ }
+ }
+
+ if (theOnlyCheck)
+ return Standard_True;
+
+ theLine->Add(aPnt);
+
+ if (!isThePrecise)
+ return Standard_True;
+
+ //Try to precise existing WLine
+ aNbPnts = theLine->NbPoints();
+ if (aNbPnts >= 3)
+ {
+ Standard_Real aU1 = 0.0, aU2 = 0.0, aU3 = 0.0, aV = 0.0;
+ if (isTheReverse)
+ {
+ theLine->Value(aNbPnts).ParametersOnS2(aU3, aV);
+ theLine->Value(aNbPnts - 1).ParametersOnS2(aU2, aV);
+ theLine->Value(aNbPnts - 2).ParametersOnS2(aU1, aV);
+ }
+ else
+ {
+ theLine->Value(aNbPnts).ParametersOnS1(aU3, aV);
+ theLine->Value(aNbPnts - 1).ParametersOnS1(aU2, aV);
+ theLine->Value(aNbPnts - 2).ParametersOnS1(aU1, aV);
+ }
+
+ const Standard_Real aStepPrev = aU2 - aU1;
+ const Standard_Real aStep = aU3 - aU2;
+
+ const Standard_Integer aDeltaStep = RealToInt(aStepPrev / aStep);
+
+ if ((1 < aDeltaStep) && (aDeltaStep < 2000))
+ {
+ //Add new points in case of non-uniform distribution of existing points
+ SeekAdditionalPoints(theQuad1,
+ theQuad2,
+ theLine,
+ theCoeffs,
+ theWLIndex,
+ aDeltaStep,
+ aNbPnts - 2,
+ aNbPnts - 1,
+ theTol2D,
+ thePeriodOfSurf1,
+ isTheReverse);
+ }
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : AddBoundaryPoint
+//purpose : Find intersection point on V-boundary.
+//=======================================================================
+void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
+ const Standard_Real theU1,
+ const Standard_Real theU1Min,
+ const Standard_Real theU2,
+ const Standard_Real theV1,
+ const Standard_Real theV1Prev,
+ const Standard_Real theV2,
+ const Standard_Real theV2Prev,
+ const Standard_Integer theWLIndex,
+ const Standard_Boolean theFlForce,
+ Standard_Boolean& isTheFound1,
+ Standard_Boolean& isTheFound2) const
+{
+ Standard_Real aUSurf1f = 0.0, //const
+ aUSurf1l = 0.0, aVSurf1f = 0.0, aVSurf1l = 0.0;
+ Standard_Real aUSurf2f = 0.0, //const
+ aUSurf2l = 0.0, aVSurf2f = 0.0, aVSurf2l = 0.0;
+
+ myUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
+ myUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
+
+ const Standard_Integer aSize = 4;
+ const Standard_Real anArrVzad[aSize] = {aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l};
+
+ StPInfo aUVPoint[aSize];
+
+ for (Standard_Integer anIDSurf = 0; anIDSurf < 4; anIDSurf += 2)
+ {
+ const Standard_Real aVf = (anIDSurf == 0) ? theV1 : theV2, aVl = (anIDSurf == 0) ? theV1Prev : theV2Prev;
+
+ const SearchBoundType aTS = (anIDSurf == 0) ? SearchV1 : SearchV2;
+
+ for (Standard_Integer anIDBound = 0; anIDBound < 2; anIDBound++)
+ {
+ const Standard_Integer anIndex = anIDSurf + anIDBound;
+
+ aUVPoint[anIndex].mySurfID = anIDSurf;
+
+ if ((Abs(aVf - anArrVzad[anIndex]) > myTol2D) && ((aVf - anArrVzad[anIndex]) * (aVl - anArrVzad[anIndex]) > 0.0))
+ {
+ continue;
+ }
+
+ //Segment [aVf, aVl] intersects at least one V-boundary (first or last)
+ // (in general, case is possible, when aVf > aVl).
+
+ // Precise intersection point
+ const Standard_Boolean aRes =
+ SearchOnVBounds(aTS, anArrVzad[anIndex], (anIDSurf == 0) ? theV2 : theV1, theU2, theU1, aUVPoint[anIndex].myU1);
+
+ // aUVPoint[anIndex].myU1 is considered to be nearer to theU1 than
+ // to theU1+/-Period
+ if (!aRes || (aUVPoint[anIndex].myU1 >= theU1) || (aUVPoint[anIndex].myU1 < theU1Min))
+ {
+ //Intersection point is not found or out of the domain
+ aUVPoint[anIndex].myU1 = RealLast();
+ continue;
+ }
+ else
+ {
+ //intersection point is found
+
+ Standard_Real &aU1 = aUVPoint[anIndex].myU1, &aU2 = aUVPoint[anIndex].myU2, &aV1 = aUVPoint[anIndex].myV1,
+ &aV2 = aUVPoint[anIndex].myV2;
+ aU2 = theU2;
+ aV1 = theV1;
+ aV2 = theV2;
+
+ if (!ComputationMethods::CylCylComputeParameters(aU1, theWLIndex, myCoeffs, aU2, aV1, aV2))
+ {
+ // Found point is wrong
+ aU1 = RealLast();
+ continue;
+ }
+
+ //Point on true V-boundary.
+ if (aTS == SearchV1)
+ aV1 = anArrVzad[anIndex];
+ else //if(aTS[anIndex] == SearchV2)
+ aV2 = anArrVzad[anIndex];
+ }
+ }
+ }
+
+ // Sort with acceding U1-parameter.
+ std::sort(aUVPoint, aUVPoint + aSize);
+
+ isTheFound1 = isTheFound2 = Standard_False;
+
+ //Adding found points on boundary in the WLine.
+ for (Standard_Integer i = 0; i < aSize; i++)
+ {
+ if (aUVPoint[i].myU1 == RealLast())
+ break;
+
+ if (!AddPointIntoWL(myQuad1,
+ myQuad2,
+ myCoeffs,
+ myIsReverse,
+ Standard_False,
+ gp_Pnt2d(aUVPoint[i].myU1, aUVPoint[i].myV1),
+ gp_Pnt2d(aUVPoint[i].myU2, aUVPoint[i].myV2),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ myPeriod,
+ theWL->Curve(),
+ theWLIndex,
+ myTol3D,
+ myTol2D,
+ theFlForce))
+ {
+ continue;
+ }
+
+ if (aUVPoint[i].mySurfID == 0)
+ {
+ isTheFound1 = Standard_True;
+ }
+ else
+ {
+ isTheFound2 = Standard_True;
+ }
+ }
+}
+
+//=======================================================================
+//function : SeekAdditionalPoints
+//purpose : Inserts additional intersection points between neighbor points.
+// This action is bone with several iterations. During every iteration,
+// new point is inserted in middle of every interval.
+// The process will be finished if NbPoints >= theMinNbPoints.
+//=======================================================================
+static void SeekAdditionalPoints(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Handle(IntSurf_LineOn2S)& theLine,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Integer theWLIndex,
+ const Standard_Integer theMinNbPoints,
+ const Standard_Integer theStartPointOnLine,
+ const Standard_Integer theEndPointOnLine,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriodOfSurf2,
+ const Standard_Boolean isTheReverse)
+{
+ if (theLine.IsNull())
+ return;
+
+ Standard_Integer aNbPoints = theEndPointOnLine - theStartPointOnLine + 1;
+
+ Standard_Real aMinDeltaParam = theTol2D;
+
+ {
+ Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
+
+ if (isTheReverse)
+ {
+ theLine->Value(theStartPointOnLine).ParametersOnS2(u1, v1);
+ theLine->Value(theEndPointOnLine).ParametersOnS2(u2, v2);
+ }
+ else
+ {
+ theLine->Value(theStartPointOnLine).ParametersOnS1(u1, v1);
+ theLine->Value(theEndPointOnLine).ParametersOnS1(u2, v2);
+ }
+
+ aMinDeltaParam = Max(Abs(u2 - u1) / IntToReal(theMinNbPoints), aMinDeltaParam);
+ }
+
+ Standard_Integer aLastPointIndex = theEndPointOnLine;
+ Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
+
+ Standard_Integer aNbPointsPrev = 0;
+ do
+ {
+ aNbPointsPrev = aNbPoints;
+ for (Standard_Integer fp = theStartPointOnLine, lp = 0; fp < aLastPointIndex; fp = lp + 1)
+ {
+ Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
+ Standard_Real U1l = 0.0, V1l = 0.0; //last point in 1st suraface
+
+ Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
+ Standard_Real U2l = 0.0, V2l = 0.0; //last point in 2nd suraface
+
+ lp = fp + 1;
+
+ if (isTheReverse)
+ {
+ theLine->Value(fp).ParametersOnS2(U1f, V1f);
+ theLine->Value(lp).ParametersOnS2(U1l, V1l);
+
+ theLine->Value(fp).ParametersOnS1(U2f, V2f);
+ theLine->Value(lp).ParametersOnS1(U2l, V2l);
+ }
+ else
+ {
+ theLine->Value(fp).ParametersOnS1(U1f, V1f);
+ theLine->Value(lp).ParametersOnS1(U1l, V1l);
+
+ theLine->Value(fp).ParametersOnS2(U2f, V2f);
+ theLine->Value(lp).ParametersOnS2(U2l, V2l);
+ }
+
+ if (Abs(U1l - U1f) <= aMinDeltaParam)
+ {
+ //Step is minimal. It is not necessary to divide it.
+ continue;
+ }
+
+ U1prec = 0.5 * (U1f + U1l);
+
+ if (!ComputationMethods::CylCylComputeParameters(U1prec, theWLIndex, theCoeffs, U2prec, V1prec, V2prec))
+ {
+ continue;
+ }
+
+ MinMax(U2f, U2l);
+ if (!InscribePoint(U2f, U2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False))
+ {
+ continue;
+ }
+
+ const gp_Pnt aP1(theQuad1.Value(U1prec, V1prec)), aP2(theQuad2.Value(U2prec, V2prec));
+ const gp_Pnt aPInt(0.5 * (aP1.XYZ() + aP2.XYZ()));
+
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ std::cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << std::endl;
+#endif
+
+ IntSurf_PntOn2S anIP;
+ if (isTheReverse)
+ {
+ anIP.SetValue(aPInt, U2prec, V2prec, U1prec, V1prec);
+ }
+ else
+ {
+ anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
+ }
+
+ theLine->InsertBefore(lp, anIP);
+
+ aNbPoints++;
+ aLastPointIndex++;
+ }
+
+ if (aNbPoints >= theMinNbPoints)
+ {
+ return;
+ }
+ } while (aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev));
+}
+
+//=======================================================================
+//function : BoundariesComputing
+//purpose : Computes true domain of future intersection curve (allows
+// avoiding excess iterations)
+//=======================================================================
+Standard_Boolean WorkWithBoundaries::BoundariesComputing(const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Bnd_Range theURange[])
+{
+ //All comments to this method is related to the comment
+ //to ComputationMethods class
+
+ //So, we have the equation
+ // cos(U2-FI2)=B*cos(U1-FI1)+C
+ //Evidently,
+ // -1 <= B*cos(U1-FI1)+C <= 1
+
+ if (theCoeffs.mB > 0.0)
+ {
+ // -(1+C)/B <= cos(U1-FI1) <= (1-C)/B
+
+ if (theCoeffs.mB + Abs(theCoeffs.mC) < -1.0)
+ {
+ //(1-C)/B < -1 or -(1+C)/B > 1 ==> No solution
+
+ return Standard_False;
+ }
+ else if (theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0)
+ {
+ //(1-C)/B >= 1 and -(1+C)/B <= -1 ==> U=[0;2*PI]+aFI1
+ theURange[0].Add(theCoeffs.mFI1);
+ theURange[0].Add(thePeriod + theCoeffs.mFI1);
+ }
+ else if ((1 + theCoeffs.mC <= theCoeffs.mB) && (theCoeffs.mB <= 1 - theCoeffs.mC))
+ {
+ //(1-C)/B >= 1 and -(1+C)/B >= -1 ==>
+ //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1),
+ //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB)
+
+ Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB;
+ if (anArg > 1.0)
+ anArg = 1.0;
+ if (anArg < -1.0)
+ anArg = -1.0;
+
+ const Standard_Real aDAngle = acos(anArg);
+ theURange[0].Add(theCoeffs.mFI1);
+ theURange[0].Add(aDAngle + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod + theCoeffs.mFI1);
+ }
+ else if ((1 - theCoeffs.mC <= theCoeffs.mB) && (theCoeffs.mB <= 1 + theCoeffs.mC))
+ {
+ //(1-C)/B <= 1 and -(1+C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1
+ //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB)
+
+ Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB;
+ if (anArg > 1.0)
+ anArg = 1.0;
+ if (anArg < -1.0)
+ anArg = -1.0;
+
+ const Standard_Real aDAngle = acos(anArg);
+ theURange[0].Add(aDAngle + theCoeffs.mFI1);
+ theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1);
+ }
+ else if (theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0)
+ {
+ //(1-C)/B <= 1 and -(1+C)/B >= -1 ==>
+ //(U=[aDAngle1;aDAngle2]+aFI1) ||
+ //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
+ //where aDAngle1 = acos((1 - myCoeffs.mC) / myCoeffs.mB),
+ // aDAngle2 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB).
+
+ Standard_Real anArg1 = (1 - theCoeffs.mC) / theCoeffs.mB, anArg2 = -(theCoeffs.mC + 1) / theCoeffs.mB;
+ if (anArg1 > 1.0)
+ anArg1 = 1.0;
+ if (anArg1 < -1.0)
+ anArg1 = -1.0;
+
+ if (anArg2 > 1.0)
+ anArg2 = 1.0;
+ if (anArg2 < -1.0)
+ anArg2 = -1.0;
+
+ const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
+ //(U=[aDAngle1;aDAngle2]+aFI1) ||
+ //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
+ theURange[0].Add(aDAngle1 + theCoeffs.mFI1);
+ theURange[0].Add(aDAngle2 + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1);
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else if (theCoeffs.mB < 0.0)
+ {
+ // (1-C)/B <= cos(U1-FI1) <= -(1+C)/B
+
+ if (theCoeffs.mB + Abs(theCoeffs.mC) > 1.0)
+ {
+ // -(1+C)/B < -1 or (1-C)/B > 1 ==> No solutions
+ return Standard_False;
+ }
+ else if (-theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0)
+ {
+ // -(1+C)/B >= 1 and (1-C)/B <= -1 ==> U=[0;2*PI]+aFI1
+ theURange[0].Add(theCoeffs.mFI1);
+ theURange[0].Add(thePeriod + theCoeffs.mFI1);
+ }
+ else if ((-theCoeffs.mC - 1 <= theCoeffs.mB) && (theCoeffs.mB <= theCoeffs.mC - 1))
+ {
+ // -(1+C)/B >= 1 and (1-C)/B >= -1 ==>
+ //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1),
+ //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB)
+
+ Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB;
+ if (anArg > 1.0)
+ anArg = 1.0;
+ if (anArg < -1.0)
+ anArg = -1.0;
+
+ const Standard_Real aDAngle = acos(anArg);
+ theURange[0].Add(theCoeffs.mFI1);
+ theURange[0].Add(aDAngle + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod + theCoeffs.mFI1);
+ }
+ else if ((theCoeffs.mC - 1 <= theCoeffs.mB) && (theCoeffs.mB <= -theCoeffs.mB - 1))
+ {
+ // -(1+C)/B <= 1 and (1-C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1,
+ //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB).
+
+ Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB;
+ if (anArg > 1.0)
+ anArg = 1.0;
+ if (anArg < -1.0)
+ anArg = -1.0;
+
+ const Standard_Real aDAngle = acos(anArg);
+ theURange[0].Add(aDAngle + theCoeffs.mFI1);
+ theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1);
+ }
+ else if (-theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0)
+ {
+ // -(1+C)/B <= 1 and (1-C)/B >= -1 ==>
+ //(U=[aDAngle1;aDAngle2]+aFI1) || (U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1),
+ //where aDAngle1 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB),
+ // aDAngle2 = acos((1 - myCoeffs.mC) / myCoeffs.mB)
+
+ Standard_Real anArg1 = -(theCoeffs.mC + 1) / theCoeffs.mB, anArg2 = (1 - theCoeffs.mC) / theCoeffs.mB;
+ if (anArg1 > 1.0)
+ anArg1 = 1.0;
+ if (anArg1 < -1.0)
+ anArg1 = -1.0;
+
+ if (anArg2 > 1.0)
+ anArg2 = 1.0;
+ if (anArg2 < -1.0)
+ anArg2 = -1.0;
+
+ const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
+ theURange[0].Add(aDAngle1 + theCoeffs.mFI1);
+ theURange[0].Add(aDAngle2 + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1);
+ theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1);
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else
+ {
+ return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CriticalPointsComputing
+//purpose : theNbCritPointsMax contains true number of critical points.
+// It must be initialized correctly before function calling
+//=======================================================================
+static void CriticalPointsComputing(const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Real theUSurf1f,
+ const Standard_Real theUSurf1l,
+ const Standard_Real theUSurf2f,
+ const Standard_Real theUSurf2l,
+ const Standard_Real thePeriod,
+ const Standard_Real theTol2D,
+ Standard_Integer& theNbCritPointsMax,
+ Standard_Real theU1crit[])
+{
+ //[0...1] - in these points parameter U1 goes through
+ // the seam-edge of the first cylinder.
+ //[2...3] - First and last U1 parameter.
+ //[4...5] - in these points parameter U2 goes through
+ // the seam-edge of the second cylinder.
+ //[6...9] - in these points an intersection line goes through
+ // U-boundaries of the second surface.
+ //[10...11] - Boundary of monotonicity interval of U2(U1) function
+ // (see CylCylMonotonicity() function)
+
+ theU1crit[0] = 0.0;
+ theU1crit[1] = thePeriod;
+ theU1crit[2] = theUSurf1f;
+ theU1crit[3] = theUSurf1l;
+
+ const Standard_Real aCOS = cos(theCoeffs.mFI2);
+ const Standard_Real aBSB = Abs(theCoeffs.mB);
+ if ((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
+ {
+ Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
+ if (anArg > 1.0)
+ anArg = 1.0;
+ if (anArg < -1.0)
+ anArg = -1.0;
+
+ theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
+ theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
+ }
+
+ Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
+ Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
+ MinMax(aSf, aSl);
+
+ //In accorance with pure mathematic, theU1crit[6] and [8]
+ //must be -Precision::Infinite() instead of used +Precision::Infinite()
+ theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1
+ : Precision::Infinite();
+ theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1
+ : Precision::Infinite();
+ theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1
+ : Precision::Infinite();
+ theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1
+ : Precision::Infinite();
+
+ theU1crit[10] = theCoeffs.mFI1;
+ theU1crit[11] = M_PI + theCoeffs.mFI1;
+
+ //preparative treatment of array. This array must have faled to contain negative
+ //infinity number
+
+ for (Standard_Integer i = 0; i < theNbCritPointsMax; i++)
+ {
+ if (Precision::IsInfinite(theU1crit[i]))
+ {
+ continue;
+ }
+
+ theU1crit[i] = fmod(theU1crit[i], thePeriod);
+ if (theU1crit[i] < 0.0)
+ theU1crit[i] += thePeriod;
+ }
+
+ //Here all not infinite elements of theU1crit are in [0, thePeriod) range
+
+ do
+ {
+ std::sort(theU1crit, theU1crit + theNbCritPointsMax);
+ } while (ExcludeNearElements(theU1crit, theNbCritPointsMax, theUSurf1f, theUSurf1l, theTol2D));
+
+ //Here all not infinite elements in theU1crit are different and sorted.
+
+ while (theNbCritPointsMax > 0)
+ {
+ Standard_Real& anB = theU1crit[theNbCritPointsMax - 1];
+ if (Precision::IsInfinite(anB))
+ {
+ theNbCritPointsMax--;
+ continue;
+ }
+
+ //1st not infinte element is found
+
+ if (theNbCritPointsMax == 1)
+ break;
+
+ //Here theNbCritPointsMax > 1
+
+ Standard_Real& anA = theU1crit[0];
+
+ //Compare 1st and last significant elements of theU1crit
+ //They may still differs by period.
+
+ if (Abs(anB - anA - thePeriod) < theTol2D)
+ { //E.g. anA == 2.0e-17, anB == (thePeriod-1.0e-18)
+ anA = (anA + anB - thePeriod) / 2.0;
+ anB = Precision::Infinite();
+ theNbCritPointsMax--;
+ }
+
+ //Out of "while(theNbCritPointsMax > 0)" cycle.
+ break;
+ }
+
+ //Attention! Here theU1crit may be unsorted.
+}
+
+//=======================================================================
+//function : BoundaryEstimation
+//purpose : Rough estimation of the parameter range.
+//=======================================================================
+void WorkWithBoundaries::BoundaryEstimation(const gp_Cylinder& theCy1,
+ const gp_Cylinder& theCy2,
+ Bnd_Range& theOutBoxS1,
+ Bnd_Range& theOutBoxS2) const
+{
+ const gp_Dir & aD1 = theCy1.Axis().Direction(), &aD2 = theCy2.Axis().Direction();
+ const Standard_Real aR1 = theCy1.Radius(), aR2 = theCy2.Radius();
+
+ //Let consider a parallelogram. Its edges are parallel to aD1 and aD2.
+ //Its altitudes are equal to 2*aR1 and 2*aR2 (diameters of the cylinders).
+ //In fact, this parallelogram is a projection of the cylinders to the plane
+ //created by the intersected axes aD1 and aD2 (if the axes are skewed then
+ //one axis can be translated by parallel shifting till intersection).
+
+ const Standard_Real aCosA = aD1.Dot(aD2);
+ const Standard_Real aSqSinA = aD1.XYZ().CrossSquareMagnitude(aD2.XYZ());
+
+ //If sine is small then it can be compared with angle.
+ if (aSqSinA < Precision::Angular() * Precision::Angular())
+ return;
+
+ //Half of delta V. Delta V is a distance between
+ //projections of two opposite parallelogram vertices
+ //(joined by the maximal diagonal) to the cylinder axis.
+ const Standard_Real aSinA = sqrt(aSqSinA);
+ const Standard_Real anAbsCosA = Abs(aCosA);
+ const Standard_Real aHDV1 = (aR1 * anAbsCosA + aR2) / aSinA, aHDV2 = (aR2 * anAbsCosA + aR1) / aSinA;
+
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ //The code in this block is created for test only.It is stupidly to create
+ //OCCT-test for the method, which will be changed possibly never.
+ std::cout << "Reference values: aHDV1 = " << aHDV1 << "; aHDV2 = " << aHDV2 << std::endl;
+#endif
+
+ //V-parameters of intersection point of the axes (in case of skewed axes,
+ //see comment above).
+ Standard_Real aV01 = 0.0, aV02 = 0.0;
+ ExtremaLineLine(theCy1.Axis(), theCy2.Axis(), aCosA, aSqSinA, aV01, aV02);
+
+ theOutBoxS1.Add(aV01 - aHDV1);
+ theOutBoxS1.Add(aV01 + aHDV1);
+
+ theOutBoxS2.Add(aV02 - aHDV2);
+ theOutBoxS2.Add(aV02 + aHDV2);
+
+ theOutBoxS1.Enlarge(Precision::Confusion());
+ theOutBoxS2.Enlarge(Precision::Confusion());
+
+ Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+ myUVSurf1.Get(aU1, aV1, aU2, aV2);
+ theOutBoxS1.Common(Bnd_Range(aV1, aV2));
+
+ myUVSurf2.Get(aU1, aV1, aU2, aV2);
+ theOutBoxS2.Common(Bnd_Range(aV1, aV2));
+}
+
+//=======================================================================
+//function : CyCyNoGeometric
+//purpose :
+//=======================================================================
+static IntPatch_ImpImpIntersection::IntStatus CyCyNoGeometric(const gp_Cylinder& theCyl1,
+ const gp_Cylinder& theCyl2,
+ const WorkWithBoundaries& theBW,
+ Bnd_Range theRange[],
+ const Standard_Integer theNbOfRanges /*=2*/,
+ Standard_Boolean& isTheEmpty,
+ IntPatch_SequenceOfLine& theSlin,
+ IntPatch_SequenceOfPoint& theSPnt)
+{
+ Standard_Real aUSurf1f = 0.0, aUSurf1l = 0.0, aUSurf2f = 0.0, aUSurf2l = 0.0, aVSurf1f = 0.0, aVSurf1l = 0.0, aVSurf2f = 0.0,
+ aVSurf2l = 0.0;
+
+ theBW.UVS1().Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
+ theBW.UVS2().Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
+
+ Bnd_Range aRangeS1, aRangeS2;
+ theBW.BoundaryEstimation(theCyl1, theCyl2, aRangeS1, aRangeS2);
+ if (aRangeS1.IsVoid() || aRangeS2.IsVoid())
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
+
+ {
+ //Quotation of the message from issue #26894 (author MSV):
+ //"We should return fail status from intersector if the result should be an
+ //infinite curve of non-analytical type... I propose to define the limit for the
+ //extent as the radius divided by 1e+2 and multiplied by 1e+7.
+ //Thus, taking into account the number of valuable digits (15), we provide reliable
+ //computations with an error not exceeding R/100."
+ const Standard_Real aF = 1.0e+5;
+ const Standard_Real aMaxV1Range = aF * theCyl1.Radius(), aMaxV2Range = aF * theCyl2.Radius();
+ if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range))
+ return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve;
+ }
+ //
+ Standard_Boolean isGoodIntersection = Standard_False;
+ Standard_Real anOptdu = 0.;
+ for (;;)
+ {
+ //Checking parameters of cylinders in order to define "good intersection"
+ //"Good intersection" means that axes of cylinders are almost perpendicular and
+ // one radius is much smaller than the other and small cylinder is "inside" big one.
+ const Standard_Real aToMuchCoeff = 3.;
+ const Standard_Real aCritAngle = M_PI / 18.; // 10 degree
+ Standard_Real anR1 = theCyl1.Radius();
+ Standard_Real anR2 = theCyl2.Radius();
+ Standard_Real anRmin = 0., anRmax = 0.;
+ //Radius criterion
+ if (anR1 > aToMuchCoeff * anR2)
+ {
+ anRmax = anR1;
+ anRmin = anR2;
+ }
+ else if (anR2 > aToMuchCoeff * anR1)
+ {
+ anRmax = anR2;
+ anRmin = anR1;
+ }
+ else
+ {
+ break;
+ }
+ //Angle criterion
+ const gp_Ax1& anAx1 = theCyl1.Axis();
+ const gp_Ax1& anAx2 = theCyl2.Axis();
+ if (!anAx1.IsNormal(anAx2, aCritAngle))
+ {
+ break;
+ }
+ //Placement criterion
+ gp_Lin anL1(anAx1), anL2(anAx2);
+ Standard_Real aDist = anL1.Distance(anL2);
+ if (aDist > anRmax / 2.)
+ {
+ break;
+ }
+
+ isGoodIntersection = Standard_True;
+ //Estimation of "optimal" du
+ //Relative deflection, absolut deflection is Rmin*aDeflection
+ Standard_Real aDeflection = 0.001;
+ Standard_Integer aNbP = 3;
+ if (anRmin * aDeflection > 1.e-3)
+ {
+ Standard_Real anAngle = 1.0e0 - aDeflection;
+ anAngle = 2.0e0 * ACos(anAngle);
+ aNbP = (Standard_Integer)(2. * M_PI / anAngle) + 1;
+ }
+ anOptdu = 2. * M_PI_2 / (Standard_Real)(aNbP - 1);
+ break;
+ }
+ //
+ const ComputationMethods::stCoeffsValue& anEquationCoeffs = theBW.SICoeffs();
+ const IntSurf_Quadric& aQuad1 = theBW.GetQSurface(1);
+ const IntSurf_Quadric& aQuad2 = theBW.GetQSurface(2);
+ const Standard_Boolean isReversed = theBW.IsReversed();
+ const Standard_Real aTol2D = theBW.Get2dTolerance();
+ const Standard_Real aTol3D = theBW.Get3dTolerance();
+ const Standard_Real aPeriod = 2.0 * M_PI;
+ Standard_Integer aNbMaxPoints = 1000;
+ Standard_Integer aNbMinPoints = 200;
+ Standard_Real du;
+ if (isGoodIntersection)
+ {
+ du = anOptdu;
+ aNbMaxPoints = 200;
+ aNbMinPoints = 50;
+ }
+ else
+ {
+ du = 2. * M_PI / aNbMaxPoints;
+ }
+ Standard_Integer aNbPts = Min(RealToInt((aUSurf1l - aUSurf1f) / du) + 1, RealToInt(20.0 * theCyl1.Radius()));
+ const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, aNbPts), aNbMaxPoints);
+ const Standard_Real aStepMin = Max(aTol2D, Precision::PConfusion()), aStepMax = (aUSurf1l - aUSurf1f > M_PI / 100.0)
+ ? (aUSurf1l - aUSurf1f) / IntToReal(aNbPoints)
+ : aUSurf1l - aUSurf1f;
+
+ //The main idea of the algorithm is to change U1-parameter
+ //(U-parameter of theCyl1) from aU1f to aU1l with some step
+ //(step is adaptive) and to obtain set of intersection points.
+
+ for (Standard_Integer i = 0; i < theNbOfRanges; i++)
+ {
+ if (theRange[i].IsVoid())
+ continue;
+
+ InscribeInterval(aUSurf1f, aUSurf1l, theRange[i], aTol2D, aPeriod);
+ }
+
+ if (theRange[0].Union(theRange[1]))
+ {
+ // Works only if (theNbOfRanges == 2).
+ theRange[1].SetVoid();
+ }
+
+ //Critical points are the value of U1-parameter in the points
+ //where WL must be decomposed.
+
+ //When U1 goes through critical points its value is set up to this
+ //parameter forcefully and the intersection point is added in the line.
+ //After that, the WL is broken (next U1 value will be correspond to the new WL).
+
+ //See CriticalPointsComputing(...) function to get detail information about this array.
+ const Standard_Integer aNbCritPointsMax = 12;
+ Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite(),
+ Precision::Infinite()};
+
+ //This list of critical points is not full because it does not contain any points
+ //which intersection line goes through V-bounds of cylinders in.
+ //They are computed by numerical methods on - line (during algorithm working).
+ //The moment is caught, when intersection line goes through V-bounds of any cylinder.
+
+ Standard_Integer aNbCritPoints = aNbCritPointsMax;
+ CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, aPeriod, aTol2D, aNbCritPoints, anU1crit);
+
+ //Getting Walking-line
+
+ enum WLFStatus
+ {
+ // No points have been added in WL
+ WLFStatus_Absent = 0,
+ // WL contains at least one point
+ WLFStatus_Exist = 1,
+ // WL has been finished in some critical point
+ // We should start new line
+ WLFStatus_Broken = 2
+ };
+
+ const Standard_Integer aNbWLines = 2;
+ for (Standard_Integer aCurInterval = 0; aCurInterval < theNbOfRanges; aCurInterval++)
+ {
+ //Process every continuous region
+ Standard_Boolean isAddedIntoWL[aNbWLines];
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ isAddedIntoWL[i] = Standard_False;
+
+ Standard_Real anUf = 1.0, anUl = 0.0;
+ if (!theRange[aCurInterval].GetBounds(anUf, anUl))
+ continue;
+
+ const Standard_Boolean isDeltaPeriod = IsEqual(anUl - anUf, aPeriod);
+
+ //Inscribe and sort critical points
+ for (Standard_Integer i = 0; i < aNbCritPoints; i++)
+ {
+ InscribePoint(anUf, anUl, anU1crit[i], 0.0, aPeriod, Standard_False);
+ }
+
+ std::sort(anU1crit, anU1crit + aNbCritPoints);
+
+ while (anUf < anUl)
+ {
+ //Change value of U-parameter on the 1st surface from anUf to anUl
+ //(anUf will be modified in the cycle body).
+ //Step is computed adaptively (see comments below).
+
+ Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
+ WLFStatus aWLFindStatus[aNbWLines];
+ Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
+ Standard_Real anUexpect[aNbWLines];
+ Standard_Boolean isAddingWLEnabled[aNbWLines];
+
+ Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
+ Handle(IntPatch_WLine) aWLine[aNbWLines];
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ aL2S[i] = new IntSurf_LineOn2S();
+ aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
+ aWLine[i]->SetCreatingWayInfo(IntPatch_WLine::IntPatch_WLImpImp);
+ aWLFindStatus[i] = WLFStatus_Absent;
+ isAddingWLEnabled[i] = Standard_True;
+ aU2[i] = aV1[i] = aV2[i] = 0.0;
+ aV1Prev[i] = aV2Prev[i] = 0.0;
+ anUexpect[i] = anUf;
+ }
+
+ Standard_Real aCriticalDelta[aNbCritPointsMax] = {0};
+ for (Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++)
+ { //We are not interested in elements of aCriticalDelta array
+ //if their index is greater than or equal to aNbCritPoints
+
+ aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID];
+ }
+
+ Standard_Real anU1 = anUf, aMinCriticalParam = anUf;
+ Standard_Boolean isFirst = Standard_True;
+
+ while (anU1 <= anUl)
+ {
+ //Change value of U-parameter on the 1st surface from anUf to anUl
+ //(anUf will be modified in the cycle body). However, this cycle
+ //can be broken if WL goes though some critical point.
+ //Step is computed adaptively (see comments below).
+
+ for (Standard_Integer i = 0; i < aNbCritPoints; i++)
+ {
+ if ((anU1 - anU1crit[i]) * aCriticalDelta[i] < 0.0)
+ {
+ //WL has gone through i-th critical point
+ anU1 = anU1crit[i];
+
+ for (Standard_Integer j = 0; j < aNbWLines; j++)
+ {
+ aWLFindStatus[j] = WLFStatus_Broken;
+ anUexpect[j] = anU1;
+ }
+
+ break;
+ }
+ }
+
+ if (IsEqual(anU1, anUl))
+ {
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ anUexpect[i] = anU1;
+
+ if (isDeltaPeriod)
+ {
+ //if isAddedIntoWL[i] == TRUE WLine contains only one point
+ //(which was end point of previous WLine). If we will
+ //add point found on the current step WLine will contain only
+ //two points. At that both these points will be equal to the
+ //points found earlier. Therefore, new WLine will repeat
+ //already existing WLine. Consequently, it is necessary
+ //to forbid building new line in this case.
+
+ isAddingWLEnabled[i] = (!isAddedIntoWL[i]);
+ }
+ else
+ {
+ isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) || (aWLFindStatus[i] == WLFStatus_Absent));
+ }
+ } //for(Standard_Integer i = 0; i < aNbWLines; i++)
+ }
+ else
+ {
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) || (aWLFindStatus[i] == WLFStatus_Absent));
+ } //for(Standard_Integer i = 0; i < aNbWLines; i++)
+ }
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ const Standard_Integer aNbPntsWL = aWLine[i].IsNull() ? 0 : aWLine[i]->Curve()->NbPoints();
+
+ if ((aWLFindStatus[i] == WLFStatus_Broken) || (aWLFindStatus[i] == WLFStatus_Absent))
+ { //Begin and end of WLine must be on boundary point
+ //or on seam-edge strictly (if it is possible).
+
+ Standard_Real aTol = aTol2D;
+ ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i], &aTol);
+ InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False);
+
+ aTol = Max(aTol, aTol2D);
+
+ if (Abs(aU2[i]) <= aTol)
+ aU2[i] = 0.0;
+ else if (Abs(aU2[i] - aPeriod) <= aTol)
+ aU2[i] = aPeriod;
+ else if (Abs(aU2[i] - aUSurf2f) <= aTol)
+ aU2[i] = aUSurf2f;
+ else if (Abs(aU2[i] - aUSurf2l) <= aTol)
+ aU2[i] = aUSurf2l;
+ }
+ else
+ {
+ ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
+ InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False);
+ }
+
+ if (aNbPntsWL == 0)
+ { //the line has not contained any points yet
+ if (((aUSurf2f + aPeriod - aUSurf2l) <= 2.0 * aTol2D)
+ && ((Abs(aU2[i] - aUSurf2f) < aTol2D) || (Abs(aU2[i] - aUSurf2l) < aTol2D)))
+ {
+ //In this case aU2[i] can have two values: current aU2[i] or
+ //aU2[i]+aPeriod (aU2[i]-aPeriod). It is necessary to choose
+ //correct value.
+
+ Standard_Boolean isIncreasing = Standard_True;
+ ComputationMethods::CylCylMonotonicity(anU1 + aStepMin, i, anEquationCoeffs, aPeriod, isIncreasing);
+
+ //If U2(U1) is increasing and U2 is considered to be equal aUSurf2l
+ //then after the next step (when U1 will be increased) U2 will be
+ //increased too. And we will go out of surface boundary.
+ //Therefore, If U2(U1) is increasing then U2 must be equal aUSurf2f.
+ //Analogically, if U2(U1) is decreasing.
+ if (isIncreasing)
+ {
+ aU2[i] = aUSurf2f;
+ }
+ else
+ {
+ aU2[i] = aUSurf2l;
+ }
+ }
+ }
+ else
+ { //aNbPntsWL > 0
+ if (((aUSurf2l - aUSurf2f) >= aPeriod) && ((Abs(aU2[i] - aUSurf2f) < aTol2D) || (Abs(aU2[i] - aUSurf2l) < aTol2D)))
+ { //end of the line
+ Standard_Real aU2prev = 0.0, aV2prev = 0.0;
+ if (isReversed)
+ aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev);
+ else
+ aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev);
+
+ if (2.0 * Abs(aU2prev - aU2[i]) > aPeriod)
+ {
+ if (aU2prev > aU2[i])
+ aU2[i] += aPeriod;
+ else
+ aU2[i] -= aPeriod;
+ }
+ }
+ }
+
+ ComputationMethods::CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs, aV1[i], aV2[i]);
+
+ if (isFirst)
+ {
+ aV1Prev[i] = aV1[i];
+ aV2Prev[i] = aV2[i];
+ }
+ } //for(Standard_Integer i = 0; i < aNbWLines; i++)
+
+ isFirst = Standard_False;
+
+ //Looking for points into WLine
+ Standard_Boolean isBroken = Standard_False;
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if (!isAddingWLEnabled[i])
+ {
+ Standard_Boolean isBoundIntersect = Standard_False;
+ if ((Abs(aV1[i] - aVSurf1f) <= aTol2D) || ((aV1[i] - aVSurf1f) * (aV1Prev[i] - aVSurf1f) < 0.0))
+ {
+ isBoundIntersect = Standard_True;
+ }
+ else if ((Abs(aV1[i] - aVSurf1l) <= aTol2D) || ((aV1[i] - aVSurf1l) * (aV1Prev[i] - aVSurf1l) < 0.0))
+ {
+ isBoundIntersect = Standard_True;
+ }
+ else if ((Abs(aV2[i] - aVSurf2f) <= aTol2D) || ((aV2[i] - aVSurf2f) * (aV2Prev[i] - aVSurf2f) < 0.0))
+ {
+ isBoundIntersect = Standard_True;
+ }
+ else if ((Abs(aV2[i] - aVSurf2l) <= aTol2D) || ((aV2[i] - aVSurf2l) * (aV2Prev[i] - aVSurf2l) < 0.0))
+ {
+ isBoundIntersect = Standard_True;
+ }
+
+ if (aWLFindStatus[i] == WLFStatus_Broken)
+ isBroken = Standard_True;
+
+ if (!isBoundIntersect)
+ {
+ continue;
+ }
+ else
+ {
+ anUexpect[i] = anU1;
+ }
+ }
+
+ // True if the current point already in the domain
+ const Standard_Boolean isInscribe = ((aUSurf2f - aU2[i]) <= aTol2D) && ((aU2[i] - aUSurf2l) <= aTol2D)
+ && ((aVSurf1f - aV1[i]) <= aTol2D) && ((aV1[i] - aVSurf1l) <= aTol2D)
+ && ((aVSurf2f - aV2[i]) <= aTol2D) && ((aV2[i] - aVSurf2l) <= aTol2D);
+
+ //isVIntersect == TRUE if intersection line intersects two (!)
+ //V-bounds of cylinder (1st or 2nd - no matter)
+ const Standard_Boolean isVIntersect = (((aVSurf1f - aV1[i]) * (aVSurf1f - aV1Prev[i]) < RealSmall())
+ && ((aVSurf1l - aV1[i]) * (aVSurf1l - aV1Prev[i]) < RealSmall()))
+ || (((aVSurf2f - aV2[i]) * (aVSurf2f - aV2Prev[i]) < RealSmall())
+ && ((aVSurf2l - aV2[i]) * (aVSurf2l - aV2Prev[i]) < RealSmall()));
+
+ //isFound1 == TRUE if intersection line intersects V-bounds
+ // (First or Last - no matter) of the 1st cylynder
+ //isFound2 == TRUE if intersection line intersects V-bounds
+ // (First or Last - no matter) of the 2nd cylynder
+ Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
+ Standard_Boolean isForce = Standard_False;
+
+ if (aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ if (((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1 - aUSurf1l) < aTol2D))
+ {
+ isForce = Standard_True;
+ }
+ }
+
+ theBW.AddBoundaryPoint(aWLine[i],
+ anU1,
+ aMinCriticalParam,
+ aU2[i],
+ aV1[i],
+ aV1Prev[i],
+ aV2[i],
+ aV2Prev[i],
+ i,
+ isForce,
+ isFound1,
+ isFound2);
+
+ const Standard_Boolean isPrevVBound = !isVIntersect
+ && ((Abs(aV1Prev[i] - aVSurf1f) <= aTol2D)
+ || (Abs(aV1Prev[i] - aVSurf1l) <= aTol2D)
+ || (Abs(aV2Prev[i] - aVSurf2f) <= aTol2D)
+ || (Abs(aV2Prev[i] - aVSurf2l) <= aTol2D));
+
+ aV1Prev[i] = aV1[i];
+ aV2Prev[i] = aV2[i];
+
+ if ((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken; //start a new line
+ }
+ else if (isInscribe)
+ {
+ if ((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2))
+ {
+ aWLFindStatus[i] = WLFStatus_Exist;
+ }
+
+ if ((aWLFindStatus[i] != WLFStatus_Broken) || (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl))
+ {
+ if (aWLine[i]->NbPnts() > 0)
+ {
+ Standard_Real aU2p = 0.0, aV2p = 0.0;
+ if (isReversed)
+ aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
+ else
+ aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
+
+ const Standard_Real aDelta = aU2[i] - aU2p;
+
+ if (2.0 * Abs(aDelta) > aPeriod)
+ {
+ if (aDelta > 0.0)
+ {
+ aU2[i] -= aPeriod;
+ }
+ else
+ {
+ aU2[i] += aPeriod;
+ }
+ }
+ }
+
+ if (AddPointIntoWL(aQuad1,
+ aQuad2,
+ anEquationCoeffs,
+ isReversed,
+ Standard_True,
+ gp_Pnt2d(anU1, aV1[i]),
+ gp_Pnt2d(aU2[i], aV2[i]),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ aPeriod,
+ aWLine[i]->Curve(),
+ i,
+ aTol3D,
+ aTol2D,
+ isForce))
+ {
+ if (aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ aWLFindStatus[i] = WLFStatus_Exist;
+ }
+ }
+ else if (!isFound1 && !isFound2)
+ { //We do not add any point while doing this iteration
+ if (aWLFindStatus[i] == WLFStatus_Exist)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ }
+ }
+ }
+ }
+ else
+ { //We do not add any point while doing this iteration
+ if (aWLFindStatus[i] == WLFStatus_Exist)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ }
+ }
+
+ if (aWLFindStatus[i] == WLFStatus_Broken)
+ isBroken = Standard_True;
+ } //for(Standard_Integer i = 0; i < aNbWLines; i++)
+
+ if (isBroken)
+ { //current lines are filled. Go to the next lines
+ anUf = anU1;
+
+ Standard_Boolean isAdded = Standard_True;
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if (isAddingWLEnabled[i])
+ {
+ continue;
+ }
+
+ isAdded = Standard_False;
+
+ Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
+
+ theBW.AddBoundaryPoint(aWLine[i],
+ anU1,
+ aMinCriticalParam,
+ aU2[i],
+ aV1[i],
+ aV1Prev[i],
+ aV2[i],
+ aV2Prev[i],
+ i,
+ Standard_False,
+ isFound1,
+ isFound2);
+
+ if (isFound1 || isFound2)
+ {
+ isAdded = Standard_True;
+ }
+
+ if (aWLine[i]->NbPnts() > 0)
+ {
+ Standard_Real aU2p = 0.0, aV2p = 0.0;
+ if (isReversed)
+ aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
+ else
+ aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
+
+ const Standard_Real aDelta = aU2[i] - aU2p;
+
+ if (2 * Abs(aDelta) > aPeriod)
+ {
+ if (aDelta > 0.0)
+ {
+ aU2[i] -= aPeriod;
+ }
+ else
+ {
+ aU2[i] += aPeriod;
+ }
+ }
+ }
+
+ if (AddPointIntoWL(aQuad1,
+ aQuad2,
+ anEquationCoeffs,
+ isReversed,
+ Standard_True,
+ gp_Pnt2d(anU1, aV1[i]),
+ gp_Pnt2d(aU2[i], aV2[i]),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ aPeriod,
+ aWLine[i]->Curve(),
+ i,
+ aTol3D,
+ aTol2D,
+ Standard_False))
+ {
+ isAdded = Standard_True;
+ }
+ }
+
+ if (!isAdded)
+ {
+ //Before breaking WL, we must complete it correctly
+ //(e.g. to prolong to the surface boundary).
+ //Therefore, we take the point last added in some WL
+ //(have maximal U1-parameter) and try to add it in
+ //the current WL.
+ Standard_Real anUmaxAdded = RealFirst();
+
+ {
+ Standard_Boolean isChanged = Standard_False;
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if ((aWLFindStatus[i] == WLFStatus_Absent) || (aWLine[i]->NbPnts() == 0))
+ continue;
+
+ Standard_Real aU1c = 0.0, aV1c = 0.0;
+ if (isReversed)
+ aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
+ else
+ aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
+
+ anUmaxAdded = Max(anUmaxAdded, aU1c);
+ isChanged = Standard_True;
+ }
+
+ if (!isChanged)
+ { //If anUmaxAdded were not changed in previous cycle then
+ //we would break existing WLines.
+ break;
+ }
+ }
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if (isAddingWLEnabled[i])
+ {
+ continue;
+ }
+
+ ComputationMethods::CylCylComputeParameters(anUmaxAdded, i, anEquationCoeffs, aU2[i], aV1[i], aV2[i]);
+
+ AddPointIntoWL(aQuad1,
+ aQuad2,
+ anEquationCoeffs,
+ isReversed,
+ Standard_True,
+ gp_Pnt2d(anUmaxAdded, aV1[i]),
+ gp_Pnt2d(aU2[i], aV2[i]),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ aPeriod,
+ aWLine[i]->Curve(),
+ i,
+ aTol3D,
+ aTol2D,
+ Standard_False);
+ }
+ }
+
+ break;
+ }
+
+ //Step computing
+
+ {
+ //Step of aU1-parameter is computed adaptively. The algorithm
+ //aims to provide given aDeltaV1 and aDeltaV2 values (if it is
+ //possible because the intersection line can go along V-isoline)
+ //in every iteration. It allows avoiding "flying" intersection
+ //points too far each from other (see issue #24915).
+
+ const Standard_Real aDeltaV1 = aRangeS1.Delta() / IntToReal(aNbPoints),
+ aDeltaV2 = aRangeS2.Delta() / IntToReal(aNbPoints);
+
+ math_Matrix aMatr(1, 3, 1, 5);
+
+ Standard_Real aMinUexp = RealLast();
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if (aTol2D < (anUexpect[i] - anU1))
+ {
+ continue;
+ }
+
+ if (aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ anUexpect[i] += aStepMax;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+ continue;
+ }
+ //
+ if (isGoodIntersection)
+ {
+ //Use constant step
+ anUexpect[i] += aStepMax;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+
+ continue;
+ }
+ //
+
+ Standard_Real aStepTmp = aStepMax;
+
+ const Standard_Real aSinU1 = sin(anU1), aCosU1 = cos(anU1), aSinU2 = sin(aU2[i]), aCosU2 = cos(aU2[i]);
+
+ aMatr.SetCol(1, anEquationCoeffs.mVecC1);
+ aMatr.SetCol(2, anEquationCoeffs.mVecC2);
+ aMatr.SetCol(3, anEquationCoeffs.mVecA1 * aSinU1 - anEquationCoeffs.mVecB1 * aCosU1);
+ aMatr.SetCol(4, anEquationCoeffs.mVecA2 * aSinU2 - anEquationCoeffs.mVecB2 * aCosU2);
+ aMatr.SetCol(5,
+ anEquationCoeffs.mVecA1 * aCosU1 + anEquationCoeffs.mVecB1 * aSinU1 + anEquationCoeffs.mVecA2 * aCosU2
+ + anEquationCoeffs.mVecB2 * aSinU2 + anEquationCoeffs.mVecD);
+
+ //The main idea is in solving of linearized system (2)
+ //(see description to ComputationMethods class) in order to find new U1-value
+ //to provide new value V1 or V2, which differs from current one by aDeltaV1 or
+ //aDeltaV2 respectively.
+
+ //While linearizing, following Taylor formulas are used:
+ // cos(x0+dx) = cos(x0) - sin(x0)*dx
+ // sin(x0+dx) = sin(x0) + cos(x0)*dx
+
+ //Consequently cos(U1), cos(U2), sin(U1) and sin(U2) in the system (2)
+ //must be substituted by corresponding values.
+
+ //ATTENTION!!!
+ //The solution is approximate. More over, all requirements to the
+ //linearization must be satisfied in order to obtain quality result.
+
+ if (!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp))
+ {
+ //To avoid cycling-up
+ anUexpect[i] += aStepMax;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+
+ continue;
+ }
+
+ if (aStepTmp < aStepMin)
+ aStepTmp = aStepMin;
+
+ if (aStepTmp > aStepMax)
+ aStepTmp = aStepMax;
+
+ anUexpect[i] = anU1 + aStepTmp;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+ }
+
+ anU1 = aMinUexp;
+ }
+
+ if (Precision::PConfusion() >= (anUl - anU1))
+ anU1 = anUl;
+
+ anUf = anU1;
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if (aWLine[i]->NbPnts() != 1)
+ isAddedIntoWL[i] = Standard_False;
+
+ if (anU1 == anUl)
+ { //strictly equal. Tolerance is considered above.
+ anUexpect[i] = anUl;
+ }
+ }
+ }
+
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if ((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
+ {
+ isTheEmpty = Standard_False;
+ Standard_Real u1, v1, u2, v2;
+ aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
+ IntPatch_Point aP;
+ aP.SetParameter(u1);
+ aP.SetParameters(u1, v1, u2, v2);
+ aP.SetTolerance(aTol3D);
+ aP.SetValue(aWLine[i]->Point(1).Value());
+
+ //Check whether the added point exists.
+ //It is enough to check the last point.
+ if (theSPnt.IsEmpty() || !theSPnt.Last().PntOn2S().IsSame(aP.PntOn2S(), Precision::Confusion()))
+ {
+ theSPnt.Append(aP);
+ }
+ }
+ else if (aWLine[i]->NbPnts() > 1)
+ {
+ Standard_Boolean isGood = Standard_True;
+
+ if (aWLine[i]->NbPnts() == 2)
+ {
+ const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1);
+ const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2);
+
+ if (aPf.IsSame(aPl, Precision::Confusion()))
+ isGood = Standard_False;
+ }
+ else if (aWLine[i]->NbPnts() > 2)
+ {
+ // Sometimes points of the WLine are distributed
+ // linearly and uniformly. However, such position
+ // of the points does not always describe the real intersection
+ // curve. I.e. real tangents at the ends of the intersection
+ // curve can significantly deviate from this "line" direction.
+ // Here we are processing this case by inserting additional points
+ // to the beginning/end of the WLine to make it more precise.
+ // See description to the issue #30082.
+
+ const Standard_Real aSqTol3D = aTol3D * aTol3D;
+ for (Standard_Integer j = 0; j < 2; j++)
+ {
+ // If j == 0 ==> add point at begin of WLine.
+ // If j == 1 ==> add point at end of WLine.
+
+ for (;;)
+ {
+ if (aWLine[i]->NbPnts() >= aNbMaxPoints)
+ {
+ break;
+ }
+
+ // Take 1st and 2nd point to compute the "line" direction.
+ // For our convenience, we make 2nd point be the ends of the WLine
+ // because it will be used for computation of the normals
+ // to the surfaces.
+ const Standard_Integer anIdx1 = j ? aWLine[i]->NbPnts() - 1 : 2;
+ const Standard_Integer anIdx2 = j ? aWLine[i]->NbPnts() : 1;
+
+ const gp_Pnt& aP1 = aWLine[i]->Point(anIdx1).Value();
+ const gp_Pnt& aP2 = aWLine[i]->Point(anIdx2).Value();
+
+ const gp_Vec aDir(aP1, aP2);
+
+ if (aDir.SquareMagnitude() < aSqTol3D)
+ {
+ break;
+ }
+
+ // Compute tangent in first/last point of the WLine.
+ // We do not take into account the flag "isReversed"
+ // because strict direction of the tangent is not
+ // important here (we are interested in the tangent
+ // line itself and nothing to fear if its direction
+ // is reversed).
+ const gp_Vec aN1 = aQuad1.Normale(aP2);
+ const gp_Vec aN2 = aQuad2.Normale(aP2);
+ const gp_Vec aTg(aN1.Crossed(aN2));
+
+ if (aTg.SquareMagnitude() < Precision::SquareConfusion())
+ {
+ // Tangent zone
+ break;
+ }
+
+ // Check of the bending
+ Standard_Real anAngle = aDir.Angle(aTg);
+
+ if (anAngle > M_PI_2)
+ anAngle -= M_PI;
+
+ if (Abs(anAngle) > 0.25) // ~ 14deg.
+ {
+ const Standard_Integer aNbPntsPrev = aWLine[i]->NbPnts();
+ SeekAdditionalPoints(aQuad1,
+ aQuad2,
+ aWLine[i]->Curve(),
+ anEquationCoeffs,
+ i,
+ 3,
+ anIdx1,
+ anIdx2,
+ aTol2D,
+ aPeriod,
+ isReversed);
+
+ if (aWLine[i]->NbPnts() == aNbPntsPrev)
+ {
+ // No points have been added. ==> Exit from a loop.
+ break;
+ }
+ }
+ else
+ {
+ // Good result has been achieved. ==> Exit from a loop.
+ break;
+ }
+ } // for (;;)
+ }
+ }
+
+ if (isGood)
+ {
+ isTheEmpty = Standard_False;
+ isAddedIntoWL[i] = Standard_True;
+ SeekAdditionalPoints(aQuad1,
+ aQuad2,
+ aWLine[i]->Curve(),
+ anEquationCoeffs,
+ i,
+ aNbPoints,
+ 1,
+ aWLine[i]->NbPnts(),
+ aTol2D,
+ aPeriod,
+ isReversed);
+
+ aWLine[i]->ComputeVertexParameters(aTol3D);
+ theSlin.Append(aWLine[i]);
+ }
+ }
+ else
+ {
+ isAddedIntoWL[i] = Standard_False;
+ }
+
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ aWLine[i]->Dump(0);
+#endif
+ }
+ }
+ }
+
+ //Delete the points in theSPnt, which
+ //lie at least in one of the line in theSlin.
+ for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
+ {
+ for (Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++)
+ {
+ Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNbLin)));
+
+ const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
+ const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aWLine1->NbPnts());
+
+ const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNbPnt).PntOn2S();
+ if (aPntCur.IsSame(aPntFWL1, aTol3D) || aPntCur.IsSame(aPntLWL1, aTol3D))
+ {
+ theSPnt.Remove(aNbPnt);
+ aNbPnt--;
+ break;
+ }
+ }
+ }
+
+ //Try to add new points in the neighborhood of existing point
+ for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
+ {
+ // Standard algorithm (implemented above) could not find any
+ // continuous curve in neighborhood of aPnt2S (e.g. because
+ // this curve is too small; see tests\bugs\modalg_5\bug25292_35 and _36).
+ // Here, we will try to find several new points nearer to aPnt2S.
+
+ // The algorithm below tries to find two points in every
+ // intervals [u1 - aStepMax, u1] and [u1, u1 + aStepMax]
+ // and every new point will be in maximal distance from
+ // u1. If these two points exist they will be joined
+ // by the intersection curve.
+
+ const IntPatch_Point& aPnt2S = theSPnt.Value(aNbPnt);
+
+ Standard_Real u1, v1, u2, v2;
+ aPnt2S.Parameters(u1, v1, u2, v2);
+
+ Handle(IntSurf_LineOn2S) aL2S = new IntSurf_LineOn2S();
+ Handle(IntPatch_WLine) aWLine = new IntPatch_WLine(aL2S, Standard_False);
+ aWLine->SetCreatingWayInfo(IntPatch_WLine::IntPatch_WLImpImp);
+
+ //Define the index of WLine, which lies the point aPnt2S in.
+ Standard_Integer anIndex = 0;
+
+ Standard_Real anUf = 0.0, anUl = 0.0, aCurU2 = 0.0;
+ if (isReversed)
+ {
+ anUf = Max(u2 - aStepMax, aUSurf1f);
+ anUl = Min(u2 + aStepMax, aUSurf1l);
+ aCurU2 = u1;
+ }
+ else
+ {
+ anUf = Max(u1 - aStepMax, aUSurf1f);
+ anUl = Min(u1 + aStepMax, aUSurf1l);
+ aCurU2 = u2;
+ }
+
+ const Standard_Real anUinf = anUf, anUsup = anUl, anUmid = 0.5 * (anUf + anUl);
+
+ {
+ //Find the value of anIndex variable.
+ Standard_Real aDelta = RealLast();
+ for (Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ Standard_Real anU2t = 0.0;
+ if (!ComputationMethods::CylCylComputeParameters(anUmid, i, anEquationCoeffs, anU2t))
+ continue;
+
+ Standard_Real aDU2 = fmod(Abs(anU2t - aCurU2), aPeriod);
+ aDU2 = Min(aDU2, Abs(aDU2 - aPeriod));
+ if (aDU2 < aDelta)
+ {
+ aDelta = aDU2;
+ anIndex = i;
+ }
+ }
+ }
+
+ // Bisection method is used in order to find every new point.
+ // I.e. if we need to find intersection point in the interval [anUinf, anUmid]
+ // we check the point anUC = 0.5*(anUinf+anUmid). If it is an intersection point
+ // we try to find another point in the interval [anUinf, anUC] (because we find the point in
+ // maximal distance from anUmid). If it is not then we try to find another point in the
+ // interval [anUC, anUmid]. Next iterations will be made analogically.
+ // When we find intersection point in the interval [anUmid, anUsup] we try to find
+ // another point in the interval [anUC, anUsup] if anUC is intersection point and
+ // in the interval [anUmid, anUC], otherwise.
+
+ Standard_Real anAddedPar[2] = {isReversed ? u2 : u1, isReversed ? u2 : u1};
+
+ for (Standard_Integer aParID = 0; aParID < 2; aParID++)
+ {
+ if (aParID == 0)
+ {
+ anUf = anUinf;
+ anUl = anUmid;
+ }
+ else // if(aParID == 1)
+ {
+ anUf = anUmid;
+ anUl = anUsup;
+ }
+
+ Standard_Real &aPar1 = (aParID == 0) ? anUf : anUl, &aPar2 = (aParID == 0) ? anUl : anUf;
+
+ while (Abs(aPar2 - aPar1) > aStepMin)
+ {
+ Standard_Real anUC = 0.5 * (anUf + anUl);
+ Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
+ Standard_Boolean isDone = ComputationMethods::CylCylComputeParameters(anUC, anIndex, anEquationCoeffs, aU2, aV1, aV2);
+
+ if (isDone)
+ {
+ if (Abs(aV1 - aVSurf1f) <= aTol2D)
+ aV1 = aVSurf1f;
+
+ if (Abs(aV1 - aVSurf1l) <= aTol2D)
+ aV1 = aVSurf1l;
+
+ if (Abs(aV2 - aVSurf2f) <= aTol2D)
+ aV2 = aVSurf2f;
+
+ if (Abs(aV2 - aVSurf2l) <= aTol2D)
+ aV2 = aVSurf2l;
+
+ isDone = AddPointIntoWL(aQuad1,
+ aQuad2,
+ anEquationCoeffs,
+ isReversed,
+ Standard_True,
+ gp_Pnt2d(anUC, aV1),
+ gp_Pnt2d(aU2, aV2),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ aPeriod,
+ aWLine->Curve(),
+ anIndex,
+ aTol3D,
+ aTol2D,
+ Standard_False,
+ Standard_True);
+ }
+
+ if (isDone)
+ {
+ anAddedPar[0] = Min(anAddedPar[0], anUC);
+ anAddedPar[1] = Max(anAddedPar[1], anUC);
+ aPar2 = anUC;
+ }
+ else
+ {
+ aPar1 = anUC;
+ }
+ }
+ }
+
+ //Fill aWLine by additional points
+ if (anAddedPar[1] - anAddedPar[0] > aStepMin)
+ {
+ for (Standard_Integer aParID = 0; aParID < 2; aParID++)
+ {
+ Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
+ ComputationMethods::CylCylComputeParameters(anAddedPar[aParID], anIndex, anEquationCoeffs, aU2, aV1, aV2);
+
+ AddPointIntoWL(aQuad1,
+ aQuad2,
+ anEquationCoeffs,
+ isReversed,
+ Standard_True,
+ gp_Pnt2d(anAddedPar[aParID], aV1),
+ gp_Pnt2d(aU2, aV2),
+ aUSurf1f,
+ aUSurf1l,
+ aUSurf2f,
+ aUSurf2l,
+ aVSurf1f,
+ aVSurf1l,
+ aVSurf2f,
+ aVSurf2l,
+ aPeriod,
+ aWLine->Curve(),
+ anIndex,
+ aTol3D,
+ aTol2D,
+ Standard_False,
+ Standard_False);
+ }
+
+ SeekAdditionalPoints(aQuad1,
+ aQuad2,
+ aWLine->Curve(),
+ anEquationCoeffs,
+ anIndex,
+ aNbMinPoints,
+ 1,
+ aWLine->NbPnts(),
+ aTol2D,
+ aPeriod,
+ isReversed);
+
+ aWLine->ComputeVertexParameters(aTol3D);
+ theSlin.Append(aWLine);
+
+ theSPnt.Remove(aNbPnt);
+ aNbPnt--;
+ }
+ }
+
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
+}
+
+//=======================================================================
+//function : IntCyCy
+//purpose :
+//=======================================================================
+IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Bnd_Box2d& theUVSurf1,
+ const Bnd_Box2d& theUVSurf2,
+ Standard_Boolean& isTheEmpty,
+ Standard_Boolean& isTheSameSurface,
+ Standard_Boolean& isTheMultiplePoint,
+ IntPatch_SequenceOfLine& theSlin,
+ IntPatch_SequenceOfPoint& theSPnt)
+{
+ isTheEmpty = Standard_True;
+ isTheSameSurface = Standard_False;
+ isTheMultiplePoint = Standard_False;
+ theSlin.Clear();
+ theSPnt.Clear();
+
+ const gp_Cylinder aCyl1 = theQuad1.Cylinder(), aCyl2 = theQuad2.Cylinder();
+
+ IntAna_QuadQuadGeo anInter(aCyl1, aCyl2, theTol3D);
+
+ if (!anInter.IsDone())
+ {
+ return IntPatch_ImpImpIntersection::IntStatus_Fail;
+ }
+
+ if (anInter.TypeInter() != IntAna_NoGeometricSolution)
+ {
+ if (CyCyAnalyticalIntersect(theQuad1,
+ theQuad2,
+ anInter,
+ theTol3D,
+ isTheEmpty,
+ isTheSameSurface,
+ isTheMultiplePoint,
+ theSlin,
+ theSPnt))
+ {
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
+ }
+ }
+
+ //Here, intersection line is not an analytical curve(line, circle, ellipsis etc.)
+
+ Standard_Real aUSBou[2][2], aVSBou[2][2]; //const
+
+ theUVSurf1.Get(aUSBou[0][0], aVSBou[0][0], aUSBou[0][1], aVSBou[0][1]);
+ theUVSurf2.Get(aUSBou[1][0], aVSBou[1][0], aUSBou[1][1], aVSBou[1][1]);
+
+ const Standard_Real aPeriod = 2.0 * M_PI;
+ const Standard_Integer aNbWLines = 2;
+
+ const ComputationMethods::stCoeffsValue anEquationCoeffs1(aCyl1, aCyl2);
+ const ComputationMethods::stCoeffsValue anEquationCoeffs2(aCyl2, aCyl1);
+
+ //Boundaries.
+ //Intersection result can include two non-connected regions
+ //(see WorkWithBoundaries::BoundariesComputing(...) method).
+ const Standard_Integer aNbOfBoundaries = 2;
+ Bnd_Range anURange[2][aNbOfBoundaries]; //const
+
+ if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs1, aPeriod, anURange[0]))
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
+
+ if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs2, aPeriod, anURange[1]))
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
+
+ //anURange[*] can be in different periodic regions in
+ //compare with First-Last surface. E.g. the surface
+ //is full cylinder [0, 2*PI] but anURange is [5, 7].
+ //Trivial common range computation returns [5, 2*PI] and
+ //its summary length is 2*PI-5 == 1.28... only. That is wrong.
+ //This problem can be solved by the following
+ //algorithm:
+ // 1. split anURange[*] by the surface boundary;
+ // 2. shift every new range in order to inscribe it
+ // in [Ufirst, Ulast] of cylinder;
+ // 3. consider only common ranges between [Ufirst, Ulast]
+ // and new ranges.
+ //
+ // In above example, we obtain following:
+ // 1. two ranges: [5, 2*PI] and [2*PI, 7];
+ // 2. after shifting: [5, 2*PI] and [0, 7-2*PI];
+ // 3. Common ranges: ([5, 2*PI] and [0, 2*PI]) == [5, 2*PI],
+ // ([0, 7-2*PI] and [0, 2*PI]) == [0, 7-2*PI];
+ // 4. Their summary length is (2*PI-5)+(7-2*PI-0)==7-5==2 ==> GOOD.
+
+ Standard_Real aSumRange[2] = {0.0, 0.0};
+ Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
+ for (Standard_Integer aCID = 0; aCID < 2; aCID++)
+ {
+ anAlloc->Reset(false);
+ NCollection_List<Bnd_Range> aListOfRng(anAlloc);
+
+ aListOfRng.Append(anURange[aCID][0]);
+ aListOfRng.Append(anURange[aCID][1]);
+
+ const Standard_Real aSplitArr[3] = {aUSBou[aCID][0], aUSBou[aCID][1], 0.0};
+
+ NCollection_List<Bnd_Range>::Iterator anITrRng;
+ for (Standard_Integer aSInd = 0; aSInd < 3; aSInd++)
+ {
+ NCollection_List<Bnd_Range> aLstTemp(aListOfRng);
+ aListOfRng.Clear();
+ for (anITrRng.Init(aLstTemp); anITrRng.More(); anITrRng.Next())
+ {
+ Bnd_Range& aRng = anITrRng.ChangeValue();
+ aRng.Split(aSplitArr[aSInd], aListOfRng, aPeriod);
+ }
+ }
+
+ anITrRng.Init(aListOfRng);
+ for (; anITrRng.More(); anITrRng.Next())
+ {
+ Bnd_Range& aCurrRange = anITrRng.ChangeValue();
+
+ Bnd_Range aBoundR;
+ aBoundR.Add(aUSBou[aCID][0]);
+ aBoundR.Add(aUSBou[aCID][1]);
+
+ if (!InscribeInterval(aUSBou[aCID][0], aUSBou[aCID][1], aCurrRange, theTol2D, aPeriod))
+ {
+ //If aCurrRange does not have common block with
+ //[Ufirst, Ulast] of cylinder then we will try
+ //to inscribe [Ufirst, Ulast] in the boundaries of aCurrRange.
+ Standard_Real aF = 1.0, aL = 0.0;
+ if (!aCurrRange.GetBounds(aF, aL))
+ continue;
+
+ if ((aL < aUSBou[aCID][0]))
+ {
+ aCurrRange.Shift(aPeriod);
+ }
+ else if (aF > aUSBou[aCID][1])
+ {
+ aCurrRange.Shift(-aPeriod);
+ }
+ }
+
+ aBoundR.Common(aCurrRange);
+
+ const Standard_Real aDelta = aBoundR.Delta();
+
+ if (aDelta > 0.0)
+ {
+ aSumRange[aCID] += aDelta;
+ }
+ }
+ }
+
+ //The bigger range the bigger number of points in Walking-line (WLine)
+ //we will be able to add and consequently we will obtain more
+ //precise intersection line.
+ //Every point of WLine is determined as function from U1-parameter,
+ //where U1 is U-parameter on 1st quadric.
+ //Therefore, we should use quadric with bigger range as 1st parameter
+ //in IntCyCy() function.
+ //On the other hand, there is no point in reversing in case of
+ //analytical intersection (when result is line, ellipse, point...).
+ //This result is independent of the arguments order.
+ const Standard_Boolean isToReverse = (aSumRange[1] > aSumRange[0]);
+
+ if (isToReverse)
+ {
+ const WorkWithBoundaries aBoundWork(theQuad2,
+ theQuad1,
+ anEquationCoeffs2,
+ theUVSurf2,
+ theUVSurf1,
+ aNbWLines,
+ aPeriod,
+ theTol3D,
+ theTol2D,
+ Standard_True);
+
+ return CyCyNoGeometric(aCyl2, aCyl1, aBoundWork, anURange[1], aNbOfBoundaries, isTheEmpty, theSlin, theSPnt);
+ }
+ else
+ {
+ const WorkWithBoundaries aBoundWork(theQuad1,
+ theQuad2,
+ anEquationCoeffs1,
+ theUVSurf1,
+ theUVSurf2,
+ aNbWLines,
+ aPeriod,
+ theTol3D,
+ theTol2D,
+ Standard_False);
+
+ return CyCyNoGeometric(aCyl1, aCyl2, aBoundWork, anURange[0], aNbOfBoundaries, isTheEmpty, theSlin, theSPnt);
+ }
+}
+
+//=======================================================================
+//function : IntCySp
+//purpose :
+//=======================================================================
+Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tol,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ Standard_Integer i;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+ IntPatch_Point ptsol;
+ gp_Circ cirsol;
+
+ gp_Cylinder Cy;
+ gp_Sphere Sp;
+
+ if (!Reversed)
+ {
+ Cy = Quad1.Cylinder();
+ Sp = Quad2.Sphere();
+ }
+ else
+ {
+ Cy = Quad2.Cylinder();
+ Sp = Quad1.Sphere();
+ }
+ IntAna_QuadQuadGeo inter(Cy, Sp, Tol);
+
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+
+ typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Point:
+ {
+ gp_Pnt psol(inter.Point(1));
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ cirsol = inter.Circle(1);
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+
+ if (NbSol == 1)
+ {
+ gp_Vec TestCurvature(ptref, Sp.Location());
+ gp_Vec Normsp, Normcyl;
+ if (!Reversed)
+ {
+ Normcyl = Quad1.Normale(ptref);
+ Normsp = Quad2.Normale(ptref);
+ }
+ else
+ {
+ Normcyl = Quad2.Normale(ptref);
+ Normsp = Quad1.Normale(ptref);
+ }
+
+ IntSurf_Situation situcyl;
+ IntSurf_Situation situsp;
+
+ if (Normcyl.Dot(TestCurvature) > 0.)
+ {
+ situsp = IntSurf_Outside;
+ if (Normsp.Dot(Normcyl) > 0.)
+ {
+ situcyl = IntSurf_Inside;
+ }
+ else
+ {
+ situcyl = IntSurf_Outside;
+ }
+ }
+ else
+ {
+ situsp = IntSurf_Inside;
+ if (Normsp.Dot(Normcyl) > 0.)
+ {
+ situcyl = IntSurf_Outside;
+ }
+ else
+ {
+ situcyl = IntSurf_Inside;
+ }
+ }
+ Handle(IntPatch_GLine) glig;
+ if (!Reversed)
+ {
+ glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
+ }
+ else
+ {
+ glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
+ }
+ slin.Append(glig);
+ }
+ else
+ {
+ if (Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref)) > 0.0)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+
+ cirsol = inter.Circle(2);
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.0000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.0000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ case IntAna_NoGeometricSolution:
+ {
+ gp_Pnt psol;
+ Standard_Real U1, V1, U2, V2;
+ IntAna_IntQuadQuad anaint(Cy, Sp, Tol);
+ if (!anaint.IsDone())
+ {
+ return Standard_False;
+ }
+
+ if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
+ {
+ Empty = Standard_True;
+ }
+ else
+ {
+ NbSol = anaint.NbPnt();
+ for (i = 1; i <= NbSol; i++)
+ {
+ psol = anaint.Point(i);
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+
+ gp_Pnt ptvalid, ptf, ptl;
+ gp_Vec tgvalid;
+ Standard_Real first, last, para;
+ IntAna_Curve curvsol;
+ Standard_Boolean tgfound;
+ Standard_Integer kount;
+
+ NbSol = anaint.NbCurve();
+ for (i = 1; i <= NbSol; i++)
+ {
+ curvsol = anaint.Curve(i);
+ curvsol.Domain(first, last);
+ ptf = curvsol.Value(first);
+ ptl = curvsol.Value(last);
+
+ para = last;
+ kount = 1;
+ tgfound = Standard_False;
+
+ while (!tgfound)
+ {
+ para = (1.123 * first + para) / 2.123;
+ tgfound = curvsol.D1u(para, ptvalid, tgvalid);
+ if (!tgfound)
+ {
+ kount++;
+ tgfound = kount > 5;
+ }
+ }
+ Handle(IntPatch_ALine) alig;
+ if (kount <= 5)
+ {
+ Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid), Quad1.Normale(ptvalid));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ alig = new IntPatch_ALine(curvsol, Standard_False, trans1, trans2);
+ }
+ else
+ {
+ alig = new IntPatch_ALine(curvsol, Standard_False);
+ }
+ Standard_Boolean TempFalse1a = Standard_False;
+ Standard_Boolean TempFalse2a = Standard_False;
+
+ //-- ptf et ptl : points debut et fin de alig
+
+ ProcessBounds(alig, slin, Quad1, Quad2, TempFalse1a, ptf, first, TempFalse2a, ptl, last, Multpoint, Tol);
+ slin.Append(alig);
+ } //-- boucle sur les lignes
+ } //-- solution avec au moins une lihne
+ }
+ break;
+
+ default:
+ {
+ return Standard_False;
+ }
+ }
+ return Standard_True;
+}
+//=======================================================================
+//function : IntCyCo
+//purpose :
+//=======================================================================
+Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tol,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ IntPatch_Point ptsol;
+
+ Standard_Integer i;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+ gp_Circ cirsol;
+
+ gp_Cylinder Cy;
+ gp_Cone Co;
+
+ if (!Reversed)
+ {
+ Cy = Quad1.Cylinder();
+ Co = Quad2.Cone();
+ }
+ else
+ {
+ Cy = Quad2.Cylinder();
+ Co = Quad1.Cone();
+ }
+ IntAna_QuadQuadGeo inter(Cy, Co, Tol);
+
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+
+ typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Point:
+ {
+ gp_Pnt psol(inter.Point(1));
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad1.Parameters(psol, U2, V2);
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ Standard_Integer j;
+ Standard_Real qwe;
+ //
+ for (j = 1; j <= 2; ++j)
+ {
+ cirsol = inter.Circle(j);
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+ qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ case IntAna_NoGeometricSolution:
+ {
+ gp_Pnt psol;
+ Standard_Real U1, V1, U2, V2;
+ IntAna_IntQuadQuad anaint(Cy, Co, Tol);
+ if (!anaint.IsDone())
+ {
+ return Standard_False;
+ }
+
+ if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
+ {
+ Empty = Standard_True;
+ }
+ else
+ {
+ NbSol = anaint.NbPnt();
+ for (i = 1; i <= NbSol; i++)
+ {
+ psol = anaint.Point(i);
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+
+ gp_Pnt ptvalid, ptf, ptl;
+ gp_Vec tgvalid;
+ //
+ Standard_Real first, last, para;
+ Standard_Boolean tgfound, firstp, lastp, kept;
+ Standard_Integer kount;
+ //
+ //
+ //IntAna_Curve curvsol;
+ IntAna_Curve aC;
+ IntAna_ListOfCurve aLC;
+ IntAna_ListIteratorOfListOfCurve aIt;
+
+ //
+ NbSol = anaint.NbCurve();
+ for (i = 1; i <= NbSol; ++i)
+ {
+ kept = Standard_False;
+ //curvsol = anaint.Curve(i);
+ aC = anaint.Curve(i);
+ aLC.Clear();
+ ExploreCurve(Co, aC, 10. * Tol, aLC);
+ //
+ aIt.Initialize(aLC);
+ for (; aIt.More(); aIt.Next())
+ {
+ IntAna_Curve& curvsol = aIt.ChangeValue();
+ //
+ curvsol.Domain(first, last);
+ firstp = !curvsol.IsFirstOpen();
+ lastp = !curvsol.IsLastOpen();
+ if (firstp)
+ {
+ ptf = curvsol.Value(first);
+ }
+ if (lastp)
+ {
+ ptl = curvsol.Value(last);
+ }
+ para = last;
+ kount = 1;
+ tgfound = Standard_False;
+
+ while (!tgfound)
+ {
+ para = (1.123 * first + para) / 2.123;
+ tgfound = curvsol.D1u(para, ptvalid, tgvalid);
+ if (!tgfound)
+ {
+ kount++;
+ tgfound = kount > 5;
+ }
+ }
+ Handle(IntPatch_ALine) alig;
+ if (kount <= 5)
+ {
+ Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid), Quad1.Normale(ptvalid));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ alig = new IntPatch_ALine(curvsol, Standard_False, trans1, trans2);
+ kept = Standard_True;
+ }
+ else
+ {
+ ptvalid = curvsol.Value(para);
+ alig = new IntPatch_ALine(curvsol, Standard_False);
+ kept = Standard_True;
+ //-- std::cout << "Transition indeterminee" << std::endl;
+ }
+ if (kept)
+ {
+ Standard_Boolean Nfirstp = !firstp;
+ Standard_Boolean Nlastp = !lastp;
+ ProcessBounds(alig, slin, Quad1, Quad2, Nfirstp, ptf, first, Nlastp, ptl, last, Multpoint, Tol);
+ slin.Append(alig);
+ }
+ } // for (; aIt.More(); aIt.Next())
+ } // for (i = 1; i <= NbSol; ++i)
+ }
+ }
+ break;
+
+ default: return Standard_False;
+
+ } // switch (typint)
+
+ return Standard_True;
+}
+//=======================================================================
+//function : ExploreCurve
+//purpose : Splits aC on several curves in the cone apex points.
+//=======================================================================
+Standard_Boolean ExploreCurve(const gp_Cone& theCo, IntAna_Curve& theCrv, const Standard_Real theTol, IntAna_ListOfCurve& theLC)
+{
+ const Standard_Real aSqTol = theTol * theTol;
+ const gp_Pnt aPapx(theCo.Apex());
+
+ Standard_Real aT1, aT2;
+ theCrv.Domain(aT1, aT2);
+
+ theLC.Clear();
+ //
+ TColStd_ListOfReal aLParams;
+ theCrv.FindParameter(aPapx, aLParams);
+ if (aLParams.IsEmpty())
+ {
+ theLC.Append(theCrv);
+ return Standard_False;
+ }
+
+ for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next())
+ {
+ Standard_Real aPrm = anItr.Value();
+
+ if ((aPrm - aT1) < Precision::PConfusion())
+ continue;
+
+ Standard_Boolean isLast = Standard_False;
+ if ((aT2 - aPrm) < Precision::PConfusion())
+ {
+ aPrm = aT2;
+ isLast = Standard_True;
+ }
+
+ const gp_Pnt aP = theCrv.Value(aPrm);
+ const Standard_Real aSqD = aP.SquareDistance(aPapx);
+ if (aSqD < aSqTol)
+ {
+ IntAna_Curve aC1 = theCrv;
+ aC1.SetDomain(aT1, aPrm);
+ aT1 = aPrm;
+ theLC.Append(aC1);
+ }
+
+ if (isLast)
+ break;
+ }
+
+ if (theLC.IsEmpty())
+ {
+ theLC.Append(theCrv);
+ return Standard_False;
+ }
+
+ if ((aT2 - aT1) > Precision::PConfusion())
+ {
+ IntAna_Curve aC1 = theCrv;
+ aC1.SetDomain(aT1, aT2);
+ theLC.Append(aC1);
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : IntCoCo
+//purpose :
+//=======================================================================
+Standard_Boolean IntCoCo(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tol,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Same,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ Standard_Integer i, NbSol;
+ Standard_Real U1, V1, U2, V2;
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+ //
+ gp_Cone Co1(Quad1.Cone());
+ gp_Cone Co2(Quad2.Cone());
+ //
+ IntAna_QuadQuadGeo inter(Co1, Co2, Tol);
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+ //
+ typint = inter.TypeInter();
+ NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+ Same = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Same:
+ {
+ Same = Standard_True;
+ }
+ break;
+
+ //modified by NIZNHY-PKV Wed Nov 30 12:56:06 2005f
+ case IntAna_Line:
+ {
+ Standard_Real para, aDot;
+ gp_Pnt aPApex1, aPApex2, ptbid;
+ gp_Lin linsol;
+ gp_Vec NormC1, NormC2;
+ IntPatch_Point aPtsol;
+ Handle(IntPatch_GLine) glig;
+ //
+ aPApex1 = Co1.Apex();
+ aPApex2 = Co2.Apex();
+ //
+ if (NbSol == 1)
+ {
+ IntSurf_Situation situC1, situC2;
+ //
+ linsol = inter.Line(1);
+ para = ElCLib::Parameter(linsol, aPApex1);
+ ptbid = ElCLib::Value(para + 5., linsol);
+ Quad1.Parameters(aPApex1, U1, V1);
+ Quad2.Parameters(aPApex1, U2, V2);
+ //
+ aPtsol.SetValue(aPApex1, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(para);
+ //
+ NormC1 = Quad1.Normale(ptbid);
+ NormC2 = Quad2.Normale(ptbid);
+ aDot = NormC1.Dot(NormC2);
+ if (aDot < 0.)
+ {
+ situC1 = IntSurf_Outside;
+ situC2 = IntSurf_Outside;
+ }
+ else
+ {
+ Standard_Real aR1, aR2;
+ gp_Lin aLAx1(aPApex1, Co1.Axis().Direction());
+ gp_Lin aLAx2(aPApex2, Co2.Axis().Direction());
+ //
+ aR1 = aLAx1.Distance(ptbid);
+ aR2 = aLAx2.Distance(ptbid);
+ //
+ situC1 = IntSurf_Inside;
+ situC2 = IntSurf_Outside;
+ if (aR1 > aR2)
+ { // Intersection line parametrizes from Apex1 to Apex2,
+ situC1 = IntSurf_Outside; // So the distance between ptbid and aLAx1 is greater than the
+ situC2 = IntSurf_Inside; // distance between ptbid and aLAx2 and in that case Cone2
+ // is inside Cone 1
+ }
+ }
+ // 1
+ glig = new IntPatch_GLine(linsol, Standard_True, situC1, situC2);
+ glig->AddVertex(aPtsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ // 2
+ linsol.SetDirection(linsol.Direction().Reversed());
+ para = ElCLib::Parameter(linsol, aPApex1);
+ aPtsol.SetParameter(para);
+
+ glig = new IntPatch_GLine(linsol, Standard_True, situC2, situC1);
+ glig->AddVertex(aPtsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ } // if (NbSol==1) {
+ //////////////////////
+ else if (NbSol == 2)
+ {
+ //
+ for (i = 1; i <= 2; ++i)
+ {
+ linsol = inter.Line(i);
+ para = ElCLib::Parameter(linsol, aPApex1);
+ ptbid = ElCLib::Value(para + 5., linsol);
+ Quad1.Parameters(aPApex1, U1, V1);
+ Quad2.Parameters(aPApex1, U2, V2);
+ //
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ if (linsol.Direction().DotCross(Quad2.Normale(ptbid), Quad1.Normale(ptbid)) > 0.)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ //
+ Multpoint = Standard_True;
+ // 1,3
+ aPtsol.SetValue(aPApex1, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(para);
+ aPtsol.SetMultiple(Standard_True);
+
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ glig->AddVertex(aPtsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ // 2,4
+ linsol.SetDirection(linsol.Direction().Reversed());
+ para = ElCLib::Parameter(linsol, aPApex1);
+ aPtsol.SetParameter(para);
+ glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
+ glig->AddVertex(aPtsol);
+ glig->SetFirstPoint(1);
+ slin.Append(glig);
+ //
+ } //for (i=1; i<=2; ++i)
+ } //else if (NbSol==2)
+ }
+ break;
+ //modified by NIZNHY-PKV Wed Nov 30 12:56:10 2005t
+
+ case IntAna_Point:
+ {
+ gp_Pnt ptcontact;
+ gp_Pnt apex1(Co1.Apex());
+ gp_Pnt apex2(Co2.Apex());
+ Standard_Real param1, param2;
+ Standard_Real paramapex1 = ElCLib::LineParameter(Co1.Axis(), apex1);
+ Standard_Real paramapex2 = ElCLib::LineParameter(Co2.Axis(), apex2);
+ for (i = 1; i <= NbSol; i++)
+ {
+ ptcontact = inter.Point(i);
+ param1 = ElCLib::LineParameter(Co1.Axis(), ptcontact);
+ param2 = ElCLib::LineParameter(Co2.Axis(), ptcontact);
+
+ Quad1.Parameters(ptcontact, U1, V1);
+ Quad2.Parameters(ptcontact, U2, V2);
+
+ if (apex1.Distance(ptcontact) <= Tol && apex2.Distance(ptcontact) <= Tol)
+ {
+ IntPatch_Point ptsol;
+ ptsol.SetValue(ptcontact, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ else if (param1 >= paramapex1 && param2 >= paramapex2)
+ {
+ IntPatch_Point ptsol;
+ ptsol.SetValue(ptcontact, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ }
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ IntPatch_Point aPtsol;
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ for (i = 1; i <= NbSol; i++)
+ {
+ gp_Circ cirsol = inter.Circle(i);
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ if (inter.HasCommonGen())
+ {
+ const gp_Pnt& aPChar = inter.PChar();
+ Quad1.Parameters(aPChar, U1, V1);
+ Quad2.Parameters(aPChar, U2, V2);
+ aPtsol.SetValue(aPChar, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(0.);
+ glig->AddVertex(aPtsol);
+ }
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ case IntAna_Ellipse:
+ {
+ IntPatch_Point aPtsol;
+ gp_Elips elipsol = inter.Ellipse(1);
+
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ ElCLib::D1(0., elipsol, ptref, Tgt);
+
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol, Standard_False, trans1, trans2);
+ if (inter.HasCommonGen())
+ {
+ const gp_Pnt& aPChar = inter.PChar();
+ Quad1.Parameters(aPChar, U1, V1);
+ Quad2.Parameters(aPChar, U2, V2);
+ aPtsol.SetValue(aPChar, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(0.);
+ glig->AddVertex(aPtsol);
+ }
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_Hyperbola:
+ {
+ IntPatch_Point aPtsol;
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ for (i = 1; i <= 2; i++)
+ {
+ gp_Hypr hyprsol = inter.Hyperbola(i);
+ ElCLib::D1(0., hyprsol, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(hyprsol, Standard_False, trans1, trans2);
+ if (inter.HasCommonGen())
+ {
+ const gp_Pnt& aPChar = inter.PChar();
+ Quad1.Parameters(aPChar, U1, V1);
+ Quad2.Parameters(aPChar, U2, V2);
+ aPtsol.SetValue(aPChar, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(0.);
+ glig->AddVertex(aPtsol);
+ }
+ slin.Append(glig);
+ }
+ }
+ break;
+
+ case IntAna_Parabola:
+ {
+ IntPatch_Point aPtsol;
+ gp_Parab parabsol = inter.Parabola(1);
+
+ gp_Vec Tgtorig(parabsol.YAxis().Direction());
+ Standard_Real ptran = Tgtorig.DotCross(Quad2.Normale(parabsol.Location()), Quad1.Normale(parabsol.Location()));
+ if (ptran > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (ptran < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(parabsol, Standard_False, trans1, trans2);
+ if (inter.HasCommonGen())
+ {
+ const gp_Pnt& aPChar = inter.PChar();
+ Quad1.Parameters(aPChar, U1, V1);
+ Quad2.Parameters(aPChar, U2, V2);
+ aPtsol.SetValue(aPChar, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ aPtsol.SetParameter(0.);
+ glig->AddVertex(aPtsol);
+ }
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_NoGeometricSolution:
+ {
+ gp_Pnt psol;
+ IntAna_IntQuadQuad anaint(Co1, Co2, Tol);
+ if (!anaint.IsDone())
+ {
+ return Standard_False;
+ }
+
+ if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
+ {
+ Empty = Standard_True;
+ }
+ else
+ {
+ NbSol = anaint.NbPnt();
+ for (i = 1; i <= NbSol; i++)
+ {
+ psol = anaint.Point(i);
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+
+ gp_Pnt ptvalid, ptf, ptl;
+ gp_Vec tgvalid;
+
+ Standard_Real first, last, para;
+ Standard_Boolean tgfound, firstp, lastp, kept;
+ Standard_Integer kount;
+
+ NbSol = anaint.NbCurve();
+ for (i = 1; i <= NbSol; i++)
+ {
+ Handle(IntPatch_ALine) alig;
+ kept = Standard_False;
+ IntAna_Curve curvsol = anaint.Curve(i);
+ curvsol.Domain(first, last);
+ firstp = !curvsol.IsFirstOpen();
+ lastp = !curvsol.IsLastOpen();
+ if (firstp)
+ {
+ ptf = curvsol.Value(first);
+ }
+ if (lastp)
+ {
+ ptl = curvsol.Value(last);
+ }
+ para = last;
+ kount = 1;
+ tgfound = Standard_False;
+
+ while (!tgfound)
+ {
+ para = (1.123 * first + para) / 2.123;
+ tgfound = curvsol.D1u(para, ptvalid, tgvalid);
+ if (tgvalid.SquareMagnitude() < 1e-14)
+ {
+ //-- on se trouve ds un cas ou les normales n'auront pas de sens
+ tgfound = Standard_False;
+ }
+
+ if (!tgfound)
+ {
+ kount++;
+ tgfound = kount > 5;
+ }
+ }
+ if (kount <= 5)
+ {
+ Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid), Quad1.Normale(ptvalid));
+ if (qwe > 0.000000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.000000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ alig = new IntPatch_ALine(curvsol, Standard_False, trans1, trans2);
+ kept = Standard_True;
+ }
+ else
+ {
+ ptvalid = curvsol.Value(para);
+ alig = new IntPatch_ALine(curvsol, Standard_False);
+ kept = Standard_True;
+ //-- cout << "Transition indeterminee" << endl;
+ }
+ if (kept)
+ {
+ Standard_Boolean Nfirstp = !firstp;
+ Standard_Boolean Nlastp = !lastp;
+ ProcessBounds(alig, slin, Quad1, Quad2, Nfirstp, ptf, first, Nlastp, ptl, last, Multpoint, Tol);
+ slin.Append(alig);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ return Standard_False;
+ }
+ }
+
+ //When two cones have common generatrix passing through apexes
+ //it is necessary to add it is solution
+ if (inter.HasCommonGen())
+ {
+ Standard_Real para;
+ IntPatch_Point aPtsol;
+ gp_Pnt aPApex1, aPApex2;
+ aPApex1 = Co1.Apex();
+ aPApex2 = Co2.Apex();
+ //common generatrix of cones
+ gce_MakeLin aMkLin(aPApex1, aPApex2);
+ const gp_Lin& linsol = aMkLin.Value();
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_True, IntSurf_Undecided, IntSurf_Undecided);
+
+ const gp_Pnt& aPChar = inter.PChar();
+ Quad1.Parameters(aPChar, U1, V1);
+ Quad2.Parameters(aPChar, U2, V2);
+ aPtsol.SetValue(aPChar, Tol, Standard_False);
+ aPtsol.SetParameters(U1, V1, U2, V2);
+ para = ElCLib::Parameter(linsol, aPChar);
+ aPtsol.SetParameter(para);
+ glig->AddVertex(aPtsol);
+
+ slin.Append(glig);
+ }
+
+ return Standard_True;
+}
+//=======================================================================
+//function : IntCoSp
+//purpose :
+//=======================================================================
+Standard_Boolean IntCoSp(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tol,
+ const Standard_Boolean Reversed,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Multpoint,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+{
+ Standard_Integer i;
+
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+
+ gp_Sphere Sp;
+ gp_Cone Co;
+ Standard_Real U1, V1, U2, V2;
+
+ if (!Reversed)
+ {
+ Co = Quad1.Cone();
+ Sp = Quad2.Sphere();
+ }
+ else
+ {
+ Co = Quad2.Cone();
+ Sp = Quad1.Sphere();
+ }
+ IntAna_QuadQuadGeo inter(Sp, Co, Tol);
+
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+
+ typint = inter.TypeInter();
+ Standard_Integer NbSol = inter.NbSolutions();
+ Empty = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Point:
+ {
+ gp_Pnt ptcontact;
+ gp_Pnt apex(Co.Apex());
+ Standard_Real param;
+ Standard_Real paramapex = ElCLib::LineParameter(Co.Axis(), apex);
+ for (i = 1; i <= NbSol; i++)
+ {
+ ptcontact = inter.Point(i);
+ param = ElCLib::LineParameter(Co.Axis(), ptcontact);
+ Quad1.Parameters(ptcontact, U1, V1);
+ Quad2.Parameters(ptcontact, U2, V2);
+
+ if (apex.Distance(ptcontact) <= Tol)
+ {
+ IntPatch_Point ptsol;
+ ptsol.SetValue(ptcontact, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ else if (param >= paramapex)
+ {
+ IntPatch_Point ptsol;
+ ptsol.SetValue(ptcontact, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ }
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+
+ for (i = 1; i <= NbSol; i++)
+ {
+ gp_Circ cirsol = inter.Circle(i);
+ //-- param = ElCLib::LineParameter(Co.Axis(),
+ //-- cirsol.Location());
+ //-- if (param >= paramapex) {
+
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ //-- }
+ }
+ }
+ break;
+
+ case IntAna_PointAndCircle:
+ {
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ gp_Pnt apex(Co.Apex());
+ Standard_Real param;
+ Standard_Real paramapex = ElCLib::LineParameter(Co.Axis(), apex);
+
+ // le point est necessairement l apex
+ Quad1.Parameters(apex, U1, V1);
+ Quad2.Parameters(apex, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(apex, Tol, Standard_False);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+
+ gp_Circ cirsol = inter.Circle(1);
+ param = ElCLib::LineParameter(Co.Axis(), cirsol.Location());
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+
+ if (param >= paramapex)
+ {
+ if (qwe > Precision::PConfusion())
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -Precision::PConfusion())
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ }
+ else
+ {
+ if (qwe < -Precision::PConfusion())
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe > Precision::PConfusion())
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ case IntAna_NoGeometricSolution:
+ {
+ gp_Pnt psol;
+ IntAna_IntQuadQuad anaint(Co, Sp, Tol);
+ if (!anaint.IsDone())
+ {
+ return Standard_False;
+ }
+
+ if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
+ {
+ Empty = Standard_True;
+ }
+ else
+ {
+ NbSol = anaint.NbPnt();
+ for (i = 1; i <= NbSol; i++)
+ {
+ psol = anaint.Point(i);
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+
+ gp_Pnt ptvalid, ptf, ptl;
+ gp_Vec tgvalid;
+ Standard_Real first, last, para;
+ Standard_Boolean tgfound, firstp, lastp, kept;
+ Standard_Integer kount;
+
+ NbSol = anaint.NbCurve();
+ for (i = 1; i <= NbSol; i++)
+ {
+ Handle(IntPatch_ALine) alig;
+ kept = Standard_False;
+ IntAna_Curve curvsol = anaint.Curve(i);
+ curvsol.Domain(first, last);
+ firstp = !curvsol.IsFirstOpen();
+ lastp = !curvsol.IsLastOpen();
+ if (firstp)
+ {
+ ptf = curvsol.Value(first);
+ }
+ if (lastp)
+ {
+ ptl = curvsol.Value(last);
+ }
+ para = last;
+ kount = 1;
+ tgfound = Standard_False;
+
+ while (!tgfound)
+ {
+ para = (1.123 * first + para) / 2.123;
+ tgfound = curvsol.D1u(para, ptvalid, tgvalid);
+ if (!tgfound)
+ {
+ kount++;
+ tgfound = kount > 5;
+ }
+ }
+ if (kount <= 5)
+ {
+ para = ElCLib::LineParameter(Co.Axis(), ptvalid);
+ Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid), Quad1.Normale(ptvalid));
+ if (qwe > 0.000000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.000000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ alig = new IntPatch_ALine(curvsol, Standard_False, trans1, trans2);
+ kept = Standard_True;
+ }
+ else
+ {
+ ptvalid = curvsol.Value(para);
+ para = ElCLib::LineParameter(Co.Axis(), ptvalid);
+ alig = new IntPatch_ALine(curvsol, Standard_False);
+ kept = Standard_True;
+ //-- cout << "Transition indeterminee" << endl;
+ }
+ if (kept)
+ {
+ Standard_Boolean Nfirstp = !firstp;
+ Standard_Boolean Nlastp = !lastp;
+ ProcessBounds(alig, slin, Quad1, Quad2, Nfirstp, ptf, first, Nlastp, ptl, last, Multpoint, Tol);
+ slin.Append(alig);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ return Standard_False;
+ }
+ }
+
+ return Standard_True;
+}
+//=======================================================================
+//function : IntSpSp
+//purpose :
+//=======================================================================
+Standard_Boolean IntSpSp(const IntSurf_Quadric& Quad1,
+ const IntSurf_Quadric& Quad2,
+ const Standard_Real Tol,
+ Standard_Boolean& Empty,
+ Standard_Boolean& Same,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
+
+// Traitement du cas Sphere/Sphere
+
+{
+ IntSurf_TypeTrans trans1, trans2;
+ IntAna_ResultType typint;
+ gp_Sphere sph1(Quad1.Sphere());
+ gp_Sphere sph2(Quad2.Sphere());
+
+ IntAna_QuadQuadGeo inter(sph1, sph2, Tol);
+ if (!inter.IsDone())
+ {
+ return Standard_False;
+ }
+
+ typint = inter.TypeInter();
+ Empty = Standard_False;
+ Same = Standard_False;
+
+ switch (typint)
+ {
+ case IntAna_Empty:
+ {
+ Empty = Standard_True;
+ }
+ break;
+
+ case IntAna_Same:
+ {
+ Same = Standard_True;
+ }
+ break;
+
+ case IntAna_Point:
+ {
+ gp_Pnt psol(inter.Point(1));
+ Standard_Real U1, V1, U2, V2;
+ Quad1.Parameters(psol, U1, V1);
+ Quad2.Parameters(psol, U2, V2);
+ IntPatch_Point ptsol;
+ ptsol.SetValue(psol, Tol, Standard_True);
+ ptsol.SetParameters(U1, V1, U2, V2);
+ spnt.Append(ptsol);
+ }
+ break;
+
+ case IntAna_Circle:
+ {
+ gp_Circ cirsol = inter.Circle(1);
+ gp_Pnt ptref;
+ gp_Vec Tgt;
+ ElCLib::D1(0., cirsol, ptref, Tgt);
+
+ Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref), Quad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
+ slin.Append(glig);
+ }
+ break;
+
+ default:
+ {
+ return Standard_False; // on ne doit pas passer ici
+ }
+ }
+ return Standard_True;
+}
+
+static Standard_Boolean TreatResultTorus(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const IntAna_QuadQuadGeo& anInt,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin);
+
+//=======================================================================
+//function : IntCyTo
+//purpose :
+//=======================================================================
+Standard_Boolean IntCyTo(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTolTang,
+ const Standard_Boolean bReversed,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ const gp_Cylinder aCyl = bReversed ? theQuad2.Cylinder() : theQuad1.Cylinder();
+ const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
+ //
+ IntAna_QuadQuadGeo anInt(aCyl, aTorus, theTolTang);
+ Standard_Boolean bRet = TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
+ //
+ return bRet;
+}
+
+//=======================================================================
+//function : IntCoTo
+//purpose :
+//=======================================================================
+Standard_Boolean IntCoTo(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTolTang,
+ const Standard_Boolean bReversed,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ const gp_Cone aCone = bReversed ? theQuad2.Cone() : theQuad1.Cone();
+ const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
+ //
+ IntAna_QuadQuadGeo anInt(aCone, aTorus, theTolTang);
+ Standard_Boolean bRet = TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
+ //
+ return bRet;
+}
+
+//=======================================================================
+//function : IntSpTo
+//purpose :
+//=======================================================================
+Standard_Boolean IntSpTo(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTolTang,
+ const Standard_Boolean bReversed,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ const gp_Sphere aSphere = bReversed ? theQuad2.Sphere() : theQuad1.Sphere();
+ const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
+ //
+ IntAna_QuadQuadGeo anInt(aSphere, aTorus, theTolTang);
+ Standard_Boolean bRet = TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
+ //
+ return bRet;
+}
+
+//=======================================================================
+//function : IntToTo
+//purpose :
+//=======================================================================
+Standard_Boolean IntToTo(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Standard_Real theTolTang,
+ Standard_Boolean& bSameSurf,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ const gp_Torus aTorus1 = theQuad1.Torus();
+ const gp_Torus aTorus2 = theQuad2.Torus();
+ //
+ IntAna_QuadQuadGeo anInt(aTorus1, aTorus2, theTolTang);
+ Standard_Boolean bRet = anInt.IsDone();
+ if (bRet)
+ {
+ if (anInt.TypeInter() == IntAna_Same)
+ {
+ bEmpty = Standard_False;
+ bSameSurf = Standard_True;
+ }
+ else
+ {
+ bRet = TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
+ }
+ }
+ //
+ return bRet;
+}
+
+//=======================================================================
+//function : TreatResultTorus
+//purpose :
+//=======================================================================
+static Standard_Boolean TreatResultTorus(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const IntAna_QuadQuadGeo& anInt,
+ Standard_Boolean& bEmpty,
+ IntPatch_SequenceOfLine& theSeqLin)
+{
+ Standard_Boolean bRet = anInt.IsDone();
+ //
+ if (!bRet)
+ {
+ return bRet;
+ }
+ //
+ IntAna_ResultType typint = anInt.TypeInter();
+ Standard_Integer NbSol = anInt.NbSolutions();
+ bEmpty = Standard_False;
+ //
+ switch (typint)
+ {
+ case IntAna_Empty: bEmpty = Standard_True; break;
+ //
+ case IntAna_Circle:
+ {
+ Standard_Integer i;
+ IntSurf_TypeTrans trans1, trans2;
+ gp_Vec Tgt;
+ gp_Pnt ptref;
+ //
+ for (i = 1; i <= NbSol; ++i)
+ {
+ gp_Circ aC = anInt.Circle(i);
+ if (theQuad1.TypeQuadric() == theQuad2.TypeQuadric())
+ {
+ AdjustToSeam(theQuad1.Torus(), aC);
+ }
+ ElCLib::D1(0., aC, ptref, Tgt);
+ Standard_Real qwe = Tgt.DotCross(theQuad2.Normale(ptref), theQuad1.Normale(ptref));
+ if (qwe > 0.00000001)
+ {
+ trans1 = IntSurf_Out;
+ trans2 = IntSurf_In;
+ }
+ else if (qwe < -0.00000001)
+ {
+ trans1 = IntSurf_In;
+ trans2 = IntSurf_Out;
+ }
+ else
+ {
+ trans1 = trans2 = IntSurf_Undecided;
+ }
+ //
+ Handle(IntPatch_GLine) glig = new IntPatch_GLine(aC, Standard_False, trans1, trans2);
+ theSeqLin.Append(glig);
+ }
+ }
+ break;
+ //
+ case IntAna_NoGeometricSolution:
+ default: bRet = Standard_False; break;
+ }
+ //
+ return bRet;
+}
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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.
-
-// Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455
-
-#include <IntPatch_ThePathPointOfTheSOnBounds.hxx>
-#include <IntPatch_TheSegmentOfTheSOnBounds.hxx>
-#include <IntPatch_RLine.hxx>
-#include <IntSurf.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_SequenceOfReal.hxx>
-#include <IntPatch_GLine.hxx>
-#include <Extrema_ExtPC.hxx>
-#include <GeomAdaptor_Curve.hxx>
-#include <Geom_Ellipse.hxx>
-#include <Geom_Parabola.hxx>
-#include <Geom_Hyperbola.hxx>
-#include <IntPatch_ALine.hxx>
-
-
-static void PutPointsOnLine(const Handle(Adaptor3d_Surface)& S1,
- const Handle(Adaptor3d_Surface)& S2,
- const IntPatch_SequenceOfPathPointOfTheSOnBounds&,
- const IntPatch_SequenceOfLine&,
- const Standard_Boolean,
- const Handle(Adaptor3d_TopolTool)&,
- const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Boolean,
- const Standard_Real);
-
-static Standard_Boolean MultiplePoint(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
- const Handle(Adaptor3d_TopolTool)& Domain,
- const IntSurf_Quadric& QuadSurf,
- const gp_Vec& Normale,
- const IntPatch_SequenceOfLine& slin,
- TColStd_Array1OfInteger& Done,
- TColStd_Array1OfInteger& UsedLine,
- const Standard_Integer Index,
- const Standard_Boolean OnFirst,
- const Standard_Real theToler);
-
-static Standard_Boolean PointOnSecondDom(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
- const Handle(Adaptor3d_TopolTool)& Domain,
- const IntSurf_Quadric& QuadSurf,
- const gp_Vec& Normale,
- const gp_Vec& Vtgint,
- const Handle(IntPatch_Line)& lin,
- TColStd_Array1OfInteger& Done,
- const Standard_Integer Index,
- const Standard_Real theToler);
-
-static Standard_Boolean SingleLine (const gp_Pnt&,
- const Handle(IntPatch_Line)&,
- const Standard_Real,
- Standard_Real&,
- gp_Vec&);
-
-
-static Standard_Boolean FindLine(gp_Pnt& Psurf,
- const IntPatch_SequenceOfLine& slin,
- const Standard_Real Tol,
- TColStd_ListOfReal& theLParams,
- gp_Vec& Vtgtint,
- Standard_Integer& theLineIdx,
- Standard_Integer OnlyThisLine,
- const Handle(Adaptor2d_Curve2d)& thearc,
- Standard_Real& theparameteronarc,
- gp_Pnt& thepointonarc,
- const IntSurf_Quadric& QuadSurf1,
- const IntSurf_Quadric& QuadSurf2,
- Standard_Real& theOutputToler);
-
-static void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds&,
- IntPatch_SequenceOfLine&,
- const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Boolean,
- const Standard_Real);
-
-static void ProcessRLine (IntPatch_SequenceOfLine&,
- const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean theIsReqToKeepRLine);
-
-//-- le calcul de dist est completement faux ds la routine ci dessous a revoir (lbr le 18 nov 97)
-Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf,
- const Handle(IntPatch_ALine)& alin,
- Standard_Real& para,
- const Handle(Adaptor2d_Curve2d)& thearc,
- Standard_Real& _theparameteronarc,
- gp_Pnt& thepointonarc,
- const IntSurf_Quadric& QuadSurf,
- const Standard_Real u0alin,
- const Standard_Real u1alin) {
- Standard_Real dtheta,theta;
-#ifdef OCCT_DEBUG
- //Standard_Real u,v,A,B,C,cost,sint,sign;
-#endif
- //-- recherche bete du point le plus proche de thearc->Value(...)
- dtheta = (u1alin-u0alin)*0.01;
- Standard_Real du=0.000000001;
- if (du >= dtheta)
- du = dtheta/2;
- Standard_Real distmin = RealLast();
-
- Standard_Real thetamin = 0.;
-
- Standard_Real theparameteronarc = _theparameteronarc;
- for(Standard_Real _theta=u0alin+dtheta; _theta<=u1alin-dtheta; _theta+=dtheta) {
- gp_Pnt P=alin->Value(_theta);
- Standard_Real d=P.Distance(PSurf);
- if(d<distmin) {
- thetamin=_theta;
- distmin=d;
- }
- }
-
- Standard_Real bestpara =0., besttheta =0., bestdist =0., distinit =0. ;
-
- //-- Distance initiale
- {
- gp_Pnt pp0 = alin->Value(thetamin);
- Standard_Real ua0,va0;
- QuadSurf.Parameters(pp0,ua0,va0);
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
- thearc->D1(theparameteronarc,p2d,d2d);
- gp_Vec2d PaPr(gp_Pnt2d(ua0,va0),p2d);
- distinit=PaPr.Magnitude();
- }
- theta = thetamin;
- //-- recherche a partir de theta et theparameteronarc
- Standard_Boolean cpasok=Standard_True;
- Standard_Integer nbiter=0;
- Standard_Real drmax = (thearc->LastParameter() - thearc->FirstParameter())*0.05;
- Standard_Real damax = (u1alin-u0alin)*0.05;
-
-
-
- bestdist = RealLast();
-
- do {
- Standard_Real ua0,va0,ua1,va1;
- //-- alin->Curve().InternalUVValue(theta,ua0,va0,A,B,C,cost,sint,sign);
- //-- alin->Curve().InternalUVValue(theta+du,ua1,va1,A,B,C,cost,sint,sign);
- gp_Pnt pp0 = alin->Value(theta);
- gp_Pnt pp1 = alin->Value(theta+du);
- QuadSurf.Parameters(pp0,ua0,va0);
- QuadSurf.Parameters(pp1,ua1,va1);
-
-
- gp_Vec2d D1a((ua1-ua0)/du,(va1-va0)/du);
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
- thearc->D1(theparameteronarc,p2d,d2d);
- gp_Vec2d PaPr(gp_Pnt2d(ua0,va0),p2d);
-
- Standard_Real pbd=PaPr.Magnitude();
- if(bestdist>pbd) {
- bestdist = pbd;
- bestpara = theparameteronarc;
- besttheta = theta;
- }
-
- D1a.SetCoord(-D1a.X(),-D1a.Y());
-
- Standard_Real d = D1a.X() * d2d.Y() - D1a.Y() * d2d.X();
-
- Standard_Real da = (-PaPr.X())* d2d.Y() - (-PaPr.Y()) * d2d.X();
- Standard_Real dr = D1a.X() * (-PaPr.Y()) - D1a.Y() * (-PaPr.X());
- if(Abs(d)>1e-15) {
- da/=d;
- dr/=d;
- }
- else {
- if(Abs(PaPr.X())>Abs(PaPr.Y())) {
- Standard_Real xx=PaPr.X();
- xx*=0.5;
- if(D1a.X()) {
- da = -xx/D1a.X();
- }
- if(d2d.X()) {
- dr = -xx/d2d.X();
- }
- }
- else {
- Standard_Real yy=PaPr.Y();
- yy*=0.5;
- if(D1a.Y()) {
- da = -yy/D1a.Y();
- }
- if(d2d.Y()) {
- dr = -yy/d2d.Y();
- }
- }
- }
-//-- Standard_Real da = -PaPr.Dot(D1a);
-//-- Standard_Real dr = -PaPr.Dot(d2d);
-
- if(da<-damax) da=-damax;
- else if(da>damax) da=damax;
- if(dr<-drmax) dr=-drmax;
- else if(dr>drmax) dr=drmax;
-
- if(Abs(da)<1e-10 && Abs(dr)<1e-10) {
- para = theta;
- PSurf = alin->Value(para);
- _theparameteronarc=theparameteronarc;
- thepointonarc = alin->Value(para);
- cpasok=Standard_False;
-//-- printf("\nt:%d",nbiter);
- return(Standard_True);
- }
- else {
- theta+=da;
- theparameteronarc+=dr;
- if( theparameteronarc>thearc->LastParameter() ) {
- theparameteronarc = thearc->LastParameter();
- }
- if( theparameteronarc<thearc->FirstParameter() ) {
- theparameteronarc = thearc->FirstParameter();
- }
- if( theta < u0alin) {
- theta = u0alin;
- }
- if( theta > u1alin-du) {
- theta = u1alin-du-du;
- }
- }
- nbiter++;
- }
- while(cpasok && nbiter<20);
- if(bestdist < distinit) {
- para = besttheta;
- PSurf = alin->Value(para);
- _theparameteronarc=bestpara;
- thepointonarc = alin->Value(para);
-//-- printf("\nT:%d",nbiter);
- return(Standard_True);
- }
-//-- printf("\nF:%d",nbiter);
- return(Standard_False);
-}
-
-
-
-
-
-//-- ======================================================================
-static void Recadre(const Handle(Adaptor3d_Surface)& myHS1,
- const Handle(Adaptor3d_Surface)& myHS2,
- Standard_Real& u1,
- Standard_Real& v1,
- Standard_Real& u2,
- Standard_Real& v2) {
- Standard_Real f,l,lmf,fpls2;
- GeomAbs_SurfaceType typs1 = myHS1->GetType();
- GeomAbs_SurfaceType typs2 = myHS2->GetType();
-
- Standard_Boolean myHS1IsUPeriodic,myHS1IsVPeriodic;
- switch (typs1) {
- case GeomAbs_Cylinder:
- case GeomAbs_Cone:
- case GeomAbs_Sphere:
- {
- myHS1IsUPeriodic = Standard_True;
- myHS1IsVPeriodic = Standard_False;
- break;
- }
- case GeomAbs_Torus:
- {
- myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True;
- break;
- }
- default:
- {
- //-- Le cas de biparametrees periodiques est gere en amont
- myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False;
- break;
- }
- }
-
- Standard_Boolean myHS2IsUPeriodic,myHS2IsVPeriodic;
- switch (typs2) {
- case GeomAbs_Cylinder:
- case GeomAbs_Cone:
- case GeomAbs_Sphere:
- {
- myHS2IsUPeriodic = Standard_True;
- myHS2IsVPeriodic = Standard_False;
- break;
- }
- case GeomAbs_Torus:
- {
- myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True;
- break;
- }
- default:
- {
- //-- Le cas de biparametrees periodiques est gere en amont
- myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False;
- break;
- }
- }
- if(myHS1IsUPeriodic) {
- lmf = M_PI+M_PI; //-- myHS1->UPeriod();
- f = myHS1->FirstUParameter();
- l = myHS1->LastUParameter();
- fpls2=0.5*(f+l);
- while((u1 < f)&&((fpls2-u1) > (u1+lmf-fpls2) )) { u1+=lmf; }
- while((u1 > l)&&((u1-fpls2) > (fpls2-(u1-lmf)) )) { u1-=lmf; }
-
- }
- if(myHS1IsVPeriodic) {
- lmf = M_PI+M_PI; //-- myHS1->VPeriod();
- f = myHS1->FirstVParameter();
- l = myHS1->LastVParameter();
- fpls2=0.5*(f+l);
- while((v1 < f)&&((fpls2-v1) > (v1+lmf-fpls2) )) { v1+=lmf; }
- while((v1 > l)&&((v1-fpls2) > (fpls2-(v1-lmf)) )) { v1-=lmf; }
- //-- while(v1 < f) { v1+=lmf; }
- //-- while(v1 > l) { v1-=lmf; }
- }
- if(myHS2IsUPeriodic) {
- lmf = M_PI+M_PI; //-- myHS2->UPeriod();
- f = myHS2->FirstUParameter();
- l = myHS2->LastUParameter();
- fpls2=0.5*(f+l);
- while((u2 < f)&&((fpls2-u2) > (u2+lmf-fpls2) )) { u2+=lmf; }
- while((u2 > l)&&((u2-fpls2) > (fpls2-(u2-lmf)) )) { u2-=lmf; }
- //-- while(u2 < f) { u2+=lmf; }
- //-- while(u2 > l) { u2-=lmf; }
- }
- if(myHS2IsVPeriodic) {
- lmf = M_PI+M_PI; //-- myHS2->VPeriod();
- f = myHS2->FirstVParameter();
- l = myHS2->LastVParameter();
- fpls2=0.5*(f+l);
- while((v2 < f)&&((fpls2-v2) > (v2+lmf-fpls2) )) { v2+=lmf; }
- while((v2 > l)&&((v2-fpls2) > (fpls2-(v2-lmf)) )) { v2-=lmf; }
- //-- while(v2 < f) { v2+=lmf; }
- //-- while(v2 > l) { v2-=lmf; }
- }
-}
-//=======================================================================
-//function : PutPointsOnLine
-//purpose :
-//=======================================================================
-void PutPointsOnLine(const Handle(Adaptor3d_Surface)& S1,
- const Handle(Adaptor3d_Surface)& S2,
- const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
- const IntPatch_SequenceOfLine& slin,
- const Standard_Boolean OnFirst,
- const Handle(Adaptor3d_TopolTool)& Domain,
- const IntSurf_Quadric& QuadSurf,
- const IntSurf_Quadric& OtherQuad,
- const Standard_Boolean multpoint,
- const Standard_Real Tolarc) {
-
- // Traitement des point (de listpnt) de depart. On les replace sur
- // la ligne d intersection, en leur affectant la transition correcte sur
- // cette ligne.
- Standard_Integer nbpnt = listpnt.Length();
- Standard_Integer nblin=slin.Length();
-
- if (!slin.Length() || !nbpnt) {
- return;
- }
- //
- Standard_Integer i,k;
- Standard_Integer linenumber;
- Standard_Real currentparameter,tolerance;
- Standard_Real U1,V1,U2,V2;
- Standard_Boolean goon;
-
-
- gp_Pnt Psurf, ptbid;
- gp_Vec Normale, Vtgint, Vtgrst;
-
- gp_Vec d1u,d1v;
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
-
- IntSurf_Transition Transline,Transarc;
-
- Handle(Adaptor2d_Curve2d) currentarc;
- Handle(Adaptor3d_HVertex) vtx,vtxbis;
-
- IntPatch_Point solpnt;
- IntPatch_ThePathPointOfTheSOnBounds currentpointonrst;
- IntPatch_IType TheType;
-
- TColStd_Array1OfInteger UsedLine(1,nblin);
- TColStd_Array1OfInteger Done(1,nbpnt);
- for(i=1;i<=nbpnt;i++) Done(i) = 0; //-- Initialisation a la main
-
- for (i=1; i<=nbpnt; i++) {
-
- if (Done(i) != 1) {
- currentpointonrst = listpnt.Value(i);
- Psurf = currentpointonrst.Value(); // Point dans l espace
- tolerance = currentpointonrst.Tolerance();
-
- // On recherche d abord si on a correspondance avec un "point multiple"
- UsedLine.Init(0);
-
- goon = Standard_True;
- if (multpoint) {
-#if 1
- Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
- currentarc->D1(currentparameter,p2d,d2d);
- QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-#endif
- goon = MultiplePoint(listpnt,Domain,QuadSurf,Normale,slin,Done, UsedLine,
- i, OnFirst, Tolarc);
- }
- if (goon) {
- Standard_Boolean linefound = Standard_False;
-
- for(Standard_Integer indiceline = 1; indiceline <=slin.Length(); indiceline++) {
- if( UsedLine(indiceline) != 0 )
- continue;
- linenumber = indiceline;
-
- //-- Attention , les points peuvent etre deplaces
- //-- il faut reprendre le point original
- currentpointonrst = listpnt.Value(i);
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
- Psurf = currentpointonrst.Value(); // Point dans l espace
- tolerance = currentpointonrst.Tolerance();
- //--
-
-
- // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 Begin
- if (! currentpointonrst.IsNew()) {
- Handle(Adaptor3d_HVertex) aVtx = currentpointonrst.Vertex();
- Standard_Real aVtxTol = aVtx->Resolution(currentarc);
- Standard_Real aTolAng = 0.01*tolerance;
-
- tolerance = Max(tolerance, aVtxTol);
-
- gp_Vec aNorm1 = QuadSurf.Normale(Psurf);
- gp_Vec aNorm2 = OtherQuad.Normale(Psurf);
- //
- if (aNorm1.Magnitude()>gp::Resolution() &&
- aNorm2.Magnitude()>gp::Resolution()) {
-
- if (aNorm1.IsParallel(aNorm2, aTolAng))
- tolerance = Sqrt(tolerance);
- }//
- }
- // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 End
- gp_Pnt pointonarc;
- Vtgint.SetCoord(0,0,0);
- Standard_Real aVertTol = Tolarc;
- TColStd_ListOfReal aLParams;
- linefound = FindLine(Psurf, slin, tolerance, aLParams, Vtgint, linenumber,
- indiceline, currentarc, currentparameter,
- pointonarc, QuadSurf, OtherQuad, aVertTol);
- if (linefound) {
-
-#if 1
- Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point
- currentarc = currentpointonrst.Arc();
- //-- currentparameter = currentpointonrst.Parameter();
- currentarc->D1(currentparameter,p2d,d2d);
- QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-#endif
-
-
-
- const Handle(IntPatch_Line)& lin = slin.Value(linenumber);
- TheType = lin->ArcType();
-
- if (!OnFirst) { // on cherche la correspondance entre point sur domaine
- // de la premiere surface et point sur domaine de la
- // deuxieme surface
-
- goon = PointOnSecondDom (listpnt, Domain, QuadSurf, Normale,
- Vtgint, lin, Done, i, aVertTol);
- }
-
- if (goon) {
- //-- Modification du 4 avril 97 tolerance->Tolarc
- //-- on replace sur le vertex la tolerance d entree et
- //-- non la tolerance qui a servi au FindLine
- solpnt.SetValue(Psurf, aVertTol, Standard_False);
-
- U1 = p2d.X(); V1 = p2d.Y();
- OtherQuad.Parameters(Psurf,U2,V2);
-
- if (OnFirst) {
- Recadre(S1,S2,U1,V1,U2,V2);
- solpnt.SetParameters(U1,V1,U2,V2);
- }
- else {
- Recadre(S1,S2,U2,V2,U1,V1);
- solpnt.SetParameters(U2,V2,U1,V1);
- }
-
- if (! currentpointonrst.IsNew()) {
- vtx = currentpointonrst.Vertex();
- solpnt.SetVertex(OnFirst,vtx);
- }
- else {
- //-- goon = Standard_False; ????
- }
-
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc);
- }
- solpnt.SetArc(OnFirst,currentarc, currentparameter,
- Transline,Transarc);
-
- for (TColStd_ListIteratorOfListOfReal anItr(aLParams);
- anItr.More(); anItr.Next())
- {
- solpnt.SetParameter(anItr.Value());
- if (TheType == IntPatch_Analytic)
- {
- Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(solpnt);
- }
- else
- {
- Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(solpnt);
- }
- }
-
- Done(i) = 1;
-
- if (goon) {
- for (k=i+1; k<= nbpnt; k++) {
- if (Done(k) != 1) {
- currentpointonrst = listpnt.Value(k);
- if (!currentpointonrst.IsNew()) {
- vtxbis = currentpointonrst.Vertex();
- if(vtx.IsNull()) {
- }
- else if (Domain->Identical(vtx, vtxbis)) {
- solpnt.SetVertex(OnFirst,vtxbis);
- solpnt.SetTolerance(Tolarc);
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
-
- // currentarc->D1(currentparameter,ptbid,Vtgrst);
- currentarc->D1(currentparameter,p2d,d2d);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,
- Transline,Transarc);
- }
- solpnt.SetArc(OnFirst,currentarc,currentparameter,
- Transline,Transarc);
- if (TheType == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(solpnt);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (lin)->AddVertex(solpnt);
- }
- Done(k) = 1;
- }
- }
- }
- }
- }
- }
- }
- else {
- Done(i) = 1; // il faudra tester si IsNew ou pas
- // et traiter en consequence
- }
- }
- }
- }
- }
-}
-
-
-Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
- const Handle(Adaptor3d_TopolTool)& Domain,
- const IntSurf_Quadric& QuadSurf,
- const gp_Vec& Normale,
- const IntPatch_SequenceOfLine& slin,
- TColStd_Array1OfInteger& Done,
- TColStd_Array1OfInteger& UsedLine,
- const Standard_Integer Index,
- const Standard_Boolean OnFirst,
- const Standard_Real theToler) {
-
-// Traitement des points "multiples".
-
-
- Standard_Integer k,ii,jj,nbvtx;
- Standard_Integer nblin = slin.Length();
- IntPatch_IType TheType;
-
-
- IntSurf_Transition Transline,Transarc;
-
-
- IntPatch_Point intpt;
- Handle(Adaptor2d_Curve2d) currentarc;
- Handle(Adaptor3d_HVertex) vtx,vtxbis;
-
- Standard_Integer nbpnt = listpnt.Length();
- IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index);
- IntPatch_ThePathPointOfTheSOnBounds otherpt;
- gp_Pnt Point = currentpointonrst.Value();
- TColStd_Array1OfInteger localdone(1,nbpnt); localdone.Init(0);
- for (ii=1; ii<=nbpnt; ii++) {
- localdone(ii)=Done(ii);
- }
-
- Standard_Real currentparameter;
- Standard_Real Paraint;
- gp_Vec Vtgint,Vtgrst;
- gp_Pnt ptbid;
-
- gp_Vec d1u,d1v;
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
-
- Standard_Boolean goon;
-
- Standard_Boolean Retvalue = Standard_True;
-
- for (ii = 1; ii <= nblin; ii++) {
- const Handle(IntPatch_Line)& slinValueii = slin.Value(ii);
- TheType = slinValueii->ArcType();
- if (TheType == IntPatch_Analytic) {
- nbvtx = Handle(IntPatch_ALine)::DownCast (slinValueii)->NbVertex();
- }
- else {
- nbvtx = Handle(IntPatch_GLine)::DownCast (slinValueii)->NbVertex();
- }
- jj = 1;
- while (jj <= nbvtx) {
- if (TheType == IntPatch_Analytic) {
- intpt = Handle(IntPatch_ALine)::DownCast (slinValueii)->Vertex(jj);
- }
- else {
- intpt = Handle(IntPatch_GLine)::DownCast (slinValueii)->Vertex(jj);
- }
- if (intpt.IsMultiple() &&
- (( OnFirst && !intpt.IsOnDomS1()) ||
- (!OnFirst && !intpt.IsOnDomS2()))) {
- if (Point.Distance(intpt.Value()) <= intpt.Tolerance()) {
- Retvalue = Standard_False;
- Standard_Boolean foo = SingleLine(Point,slinValueii,
- intpt.Tolerance(),Paraint,Vtgint);
- if (!foo) {
- return Standard_False; // ne doit pas se produire
- }
-
- if (!currentpointonrst.IsNew()) {
- goon = Standard_True;
- vtx = currentpointonrst.Vertex();
- intpt.SetVertex(OnFirst,vtx);
- }
- else {
- goon = Standard_False;
- }
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
- currentarc->D1(currentparameter,p2d,d2d);
- QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-
- //-- Si la normale est nulle (apex d un cone) On simule une transition UNKNOWN
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc);
- }
-
- //-- Avant, on ne mettait pas ce point (17 nov 97)
- //--printf("\n ImpImp_0 : Point(%g,%g,%g) intpt(%g,%g,%g) \n",
- //-- Point.X(),Point.Y(),Point.Z(),intpt.Value().X(),intpt.Value().Y(),intpt.Value().Z());
- intpt.SetValue(Point);
-
- intpt.SetArc(OnFirst,currentarc,currentparameter,
- Transline,Transarc);
- intpt.SetTolerance(theToler);
-
- if (TheType == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (slinValueii)->Replace(jj,intpt);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (slinValueii)->Replace(jj,intpt);
- }
- localdone(Index) = 1;
- if (goon) {
- for (k=Index+1; k<= nbpnt; k++) {
- if (Done(k) != 1) {
- otherpt= listpnt.Value(k);
- if (!otherpt.IsNew()) {
- vtxbis = otherpt.Vertex();
- if (Domain->Identical(vtx, vtxbis)) {
- intpt.SetVertex(OnFirst,vtxbis);
- currentarc = otherpt.Arc();
- currentparameter = otherpt.Parameter();
-
- currentarc->D1(currentparameter,p2d,d2d);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,
- Transline,Transarc);
- }
- intpt.SetArc(OnFirst,currentarc,currentparameter,
- Transline,Transarc);
- intpt.SetTolerance(theToler);
- if (TheType == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (slinValueii)->AddVertex(intpt);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (slinValueii)->AddVertex(intpt);
- }
- UsedLine(ii) = 1;
- Retvalue = Standard_True;
- localdone(k) = 1;
- }
- }
- }
- }
- }
-//-- jj = nbvtx +1;
- }
-//-- else {
- jj = jj+1;
-//-- }
- }
- else {
- jj = jj+1;
- }
- }
- }
-
- for (ii=1; ii<=nbpnt;ii++) {
- Done(ii) = localdone(ii);
- }
-
- return Retvalue;
-}
-
-
-
-Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
- const Handle(Adaptor3d_TopolTool)& Domain,
- const IntSurf_Quadric& QuadSurf,
- const gp_Vec& Normale,
- const gp_Vec& Vtgint,
- const Handle(IntPatch_Line)& lin,
- TColStd_Array1OfInteger& Done,
- const Standard_Integer Index,
- const Standard_Real theToler)
-
-
-// Duplication des points sur domaine de l autre surface.
-// On sait que le vertex sous-jacent est PntRef
-
-
-{
-
- Standard_Integer k,jj,nbvtx;
- IntPatch_IType TheType;
-
- IntSurf_Transition Transline,Transarc;
- IntPatch_Point intpt;
- Handle(Adaptor2d_Curve2d) currentarc;
- Handle(Adaptor3d_HVertex) vtx,vtxbis;
- gp_Pnt ptbid;
- gp_Vec Vtgrst;
-
- gp_Vec d1u,d1v;
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
-
- Standard_Integer nbpnt = listpnt.Length();
- IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index);
- Standard_Real currentparameter;
-
- Standard_Boolean goon;
- Standard_Boolean Retvalue = Standard_True;
-
- TheType = lin->ArcType();
- if (TheType == IntPatch_Analytic) {
- nbvtx = Handle(IntPatch_ALine)::DownCast (lin)->NbVertex();
- }
- else {
- nbvtx = Handle(IntPatch_GLine)::DownCast (lin)->NbVertex();
- }
- jj = 1;
- while (jj <= nbvtx) {
- if (TheType == IntPatch_Analytic) {
- intpt = Handle(IntPatch_ALine)::DownCast (lin)->Vertex(jj);
- }
- else {
- intpt = Handle(IntPatch_GLine)::DownCast (lin)->Vertex(jj);
- }
- if (!intpt.IsOnDomS2()) {
- if (currentpointonrst.Value().Distance(intpt.Value()) <=
- intpt.Tolerance()) {
- Retvalue = Standard_False;
- if (!currentpointonrst.IsNew()) {
- goon = Standard_True;
- vtx = currentpointonrst.Vertex();
- intpt.SetVertex(Standard_False,vtx);
- }
- else {
- goon = Standard_False;
- }
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
- currentarc->D1(currentparameter,p2d,d2d);
- QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc);
- }
- intpt.SetArc(Standard_False,currentarc,currentparameter,
- Transline,Transarc);
- intpt.SetTolerance(theToler);
-
- if (TheType == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (lin)->Replace(jj,intpt);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (lin)->Replace(jj,intpt);
- }
- Done(Index) = 1;
-
- if (goon) {
- for (k=Index+1; k<= nbpnt; k++) {
- if (Done(k) != 1) {
- currentpointonrst = listpnt.Value(k);
- if (!currentpointonrst.IsNew()) {
- vtxbis = currentpointonrst.Vertex();
- if (Domain->Identical(vtx, vtxbis)) {
- intpt.SetVertex(Standard_False,vtxbis);
- currentarc = currentpointonrst.Arc();
- currentparameter = currentpointonrst.Parameter();
- currentarc->D1(currentparameter,p2d,d2d);
- Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if(Normale.SquareMagnitude()<1e-16) {
- Transline.SetValue(Standard_True,IntSurf_Undecided);
- Transarc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,
- Transline,Transarc);
- }
- intpt.SetArc(Standard_False,currentarc,currentparameter,
- Transline,Transarc);
- intpt.SetTolerance(theToler);
- if (TheType == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(intpt);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (lin)->AddVertex(intpt);
- }
- Done(k) = 1;
- }
- }
- }
- }
- }
- //-- jj = nbvtx + 1;
- jj++;
- }
- else {
- jj = jj+1;
- }
- }
- else {
- jj = jj+1;
- }
- if (TheType == IntPatch_Analytic) {
- nbvtx = Handle(IntPatch_ALine)::DownCast (lin)->NbVertex();
- }
- else {
- nbvtx = Handle(IntPatch_GLine)::DownCast (lin)->NbVertex();
- }
- }
- return Retvalue;
-}
-
-
-
-Standard_Boolean FindLine(gp_Pnt& Psurf,
- const IntPatch_SequenceOfLine& slin,
- const Standard_Real Tol,
- TColStd_ListOfReal& theLParams,
- gp_Vec& Vtgtint,
- Standard_Integer& theLineIdx,
- Standard_Integer OnlyThisLine,
- const Handle(Adaptor2d_Curve2d)& thearc,
- Standard_Real& theparameteronarc,
- gp_Pnt& thepointonarc,
- const IntSurf_Quadric& QuadSurf1,
- const IntSurf_Quadric& QuadSurf2,
- Standard_Real& theOutputToler)
-{
- if ((QuadSurf1.Distance(Psurf) > Tol) || (QuadSurf2.Distance(Psurf) > Tol))
- return Standard_False;
-
-// Traitement du point de depart ayant pour representation Psurf
-// dans l espace. On recherche la ligne d intersection contenant ce point.
-// On a en sortie la ligne, et le parametre et sa tangente du point sur
-// la ligne d intersection.
- const Standard_Real aSqTol = Tol*Tol;
- Standard_Real aSqDistMin = RealLast();
- Standard_Real aSqDist, para;
- Standard_Real lower,upper;
- gp_Pnt pt;
- Standard_Integer i;
- IntPatch_IType typarc;
-
- Standard_Real aParaInt = RealLast();
- Standard_Integer nblin = slin.Length();
- for (i=1; i<=nblin; i++) {
- if(OnlyThisLine) { i=OnlyThisLine; nblin=0; }
- const Handle(IntPatch_Line)& lin = slin.Value(i);
- typarc = lin->ArcType();
- if (typarc == IntPatch_Analytic) {
- Standard_Boolean foo;
- lower = Handle(IntPatch_ALine)::DownCast (lin)->FirstParameter(foo);
- upper = Handle(IntPatch_ALine)::DownCast (lin)->LastParameter(foo);
- }
- else {
- if (Handle(IntPatch_GLine)::DownCast (lin)->HasFirstPoint()) {
- lower = Handle(IntPatch_GLine)::DownCast (lin)->FirstPoint().ParameterOnLine();
- }
- else {
- lower = RealFirst();
- }
- if (Handle(IntPatch_GLine)::DownCast (lin)->HasLastPoint()) {
- upper = Handle(IntPatch_GLine)::DownCast (lin)->LastPoint().ParameterOnLine();
- }
- else {
- upper = RealLast();
- }
- }
-
- switch (typarc) {
- case IntPatch_Lin :
- {
- para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf);
- if (para <= upper && para >= lower) {
- pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Line());
- aSqDist = Psurf.SquareDistance(pt);
- if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
- {
- aSqDistMin = aSqDist;
- aParaInt = para;
- theLineIdx = i;
- }
- }
- }
- break;
- case IntPatch_Circle :
- {
- para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Circle(),Psurf);
- if ((para <= upper && para >= lower) ||
- (para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) ||
- (para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) {
- pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Circle());
- aSqDist = Psurf.SquareDistance(pt);
- if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
- {
- aSqDistMin = aSqDist;
- aParaInt = para;
- theLineIdx = i;
- }
- }
- }
- break;
- case IntPatch_Ellipse :
- {
- para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),Psurf);
- if ((para <= upper && para >= lower) ||
- (para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) ||
- (para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) {
- pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Ellipse());
- aSqDist = Psurf.SquareDistance(pt);
- if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
- {
- aSqDistMin = aSqDist;
- aParaInt = para;
- theLineIdx = i;
- }
- }
- }
- break;
- case IntPatch_Parabola :
- {
-
-#if 0
- para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),Psurf);
- if (para <= upper && para >= lower) {
- pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Parabola());
- dist = Psurf.Distance(pt);
- if (dist< distmin) {
- distmin = dist;
- Paraint = para;
- Range = i;
- }
- }
-#else
- //-- Le calcul du parametre sur une parabole est mal fait ds ElCLib. Il ne tient pas compte
- //-- de la meilleure facon de calculer (axe X ou axe Y). Bilan : Si la parabole est tres
- //-- pointue (focal de l'ordre de 1e-2 et si le point est a un parametre grand, ca foire. )
- //-- On ne peut pas modifier faciolement ds ElCLib car on ne passe pas la focale. ...
- const gp_Parab& Parab=Handle(IntPatch_GLine)::DownCast (lin)->Parabola();
- para = ElCLib::Parameter(Parab,Psurf);
- if (para <= upper && para >= lower) {
- Standard_Integer amelioration=0;
- //-- cout<<"\n ****** \n";
- do {
- Standard_Real parabis = para+0.0000001;
-
- pt = ElCLib::Value(para,Parab);
- aSqDist = Psurf.SquareDistance(pt);
-
- const gp_Pnt ptbis = ElCLib::Value(parabis,Parab);
- const Standard_Real distbis = Psurf.Distance(ptbis);
- const Standard_Real aDist = Sqrt(aSqDist);
- const Standard_Real ddist = distbis - aDist;
-
- //--cout<<" para: "<<para<<" dist:"<<dist<<" ddist:"<<ddist<<endl;
-
- if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
- {
- aSqDistMin = aSqDist;
- aParaInt = para;
- theLineIdx = i;
- }
- if (aSqDist < Precision::SquarePConfusion())
- {
- amelioration = 100;
- }
-
- if(ddist>1.0e-9 || ddist<-1.0e-9 ) {
- para = para - aDist*(parabis - para) / ddist;
- }
- else {
- amelioration=100;
- }
- }
- while(++amelioration < 5);
- }
-
-
-#endif
- }
- break;
- case IntPatch_Hyperbola :
- {
- para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),Psurf);
- if (para <= upper && para >= lower) {
- pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola());
- aSqDist = Psurf.SquareDistance(pt);
- if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
- {
- aSqDistMin = aSqDist;
- aParaInt = para;
- theLineIdx = i;
- }
- }
- }
- break;
-
- case IntPatch_Analytic :
- {
- Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
- TColStd_ListOfReal aLParams;
- alin->FindParameter(Psurf, aLParams);
- if (!aLParams.IsEmpty())
- {
- // All found distances are already in some internal tolerance
- // set in alin->FindParameter(...) method.
-
- aSqDist = RealLast();
- for (TColStd_ListIteratorOfListOfReal anItr(aLParams);
- anItr.More(); anItr.Next())
- {
- pt = alin->Value(anItr.Value());
- const Standard_Real aSqD = Psurf.SquareDistance(pt);
- if (aSqD < aSqDist)
- {
- aSqDist = aSqD;
- }
- }
-
- if (aSqDist < aSqDistMin)
- {
- aSqDistMin = aSqDist;
- theLParams = aLParams;
- theLineIdx = i;
- }
- }
- else {
- //-- le point n a pas ete trouve par bete projection.
- //-- on essaie l intersection avec la restriction en 2d
- Standard_Real theparamonarc = theparameteronarc;
-//#ifdef OCCT_DEBUG
-// Standard_Real anpara=para;
-//#endif
- gp_Pnt CopiePsurf=Psurf;
- Standard_Boolean IntersectIsOk = IntersectionWithAnArc(CopiePsurf, alin, para,
- thearc, theparamonarc,
- thepointonarc,
- QuadSurf1,
- lower, upper);
- aSqDist = CopiePsurf.SquareDistance(Psurf);
- if(IntersectIsOk) {
- if (aSqDist < aSqTol)
- {
- theparameteronarc = theparamonarc;
- Psurf = thepointonarc;
- aSqDistMin = aSqDist;
- theLParams.Append(para);
- theLineIdx = i;
- }
- }
- }
- }
- break;
-
- case IntPatch_Walking: // impossible . c est pour eviter les warnings
- {
- }
- case IntPatch_Restriction: // impossible . c est pour eviter les warnings
- {
- }
- }
- }
-
- if (aSqDistMin == RealLast())
- return Standard_False;
-
- theOutputToler = Max(theOutputToler, Sqrt(aSqDistMin));
-
- typarc = slin.Value(theLineIdx)->ArcType();
-
- // Computation of tangent vector
- switch (typarc) {
- case IntPatch_Lin :
- theLParams.Append(aParaInt);
- Vtgtint = (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Line().Direction();
- break;
- case IntPatch_Circle :
- theLParams.Append(aParaInt);
- Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Circle(), 1);
- break;
- case IntPatch_Ellipse :
- theLParams.Append(aParaInt);
- Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Ellipse(), 1);
- break;
- case IntPatch_Parabola :
- theLParams.Append(aParaInt);
- Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Parabola(), 1);
- break;
- case IntPatch_Hyperbola :
- theLParams.Append(aParaInt);
- Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Hyperbola(), 1);
- break;
-
- case IntPatch_Analytic:
- {
- if (!Handle(IntPatch_ALine)::DownCast(slin(theLineIdx))->D1(theLParams.Last(), pt, Vtgtint))
- {
- //Previously (before the fix #29807) this code tried to process case
- //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
- //computed Vtgtint input argument value. Currently, any singularities
- //must be processed by high-level algorithms (IntPatch_SpecialPoints class).
- //Therefore this code has been deleted as deprecated.
-
- Vtgtint.SetCoord(0.0, 0.0, 0.0);
- }
- }
- break;
- case IntPatch_Walking: // impossible . c est pour eviter les warnings
- {
- }
- case IntPatch_Restriction: // impossible . c est pour eviter les warnings
- {
- }
-
- }
- return Standard_True;
-}
-
-//=======================================================================
-//function : SingleLine
-//purpose : Traitement du point de depart ayant pour representation Psurf
-// dans l espace. On le replace sur la ligne d intersection; On a en sortie
-// son parametre et sa tangente sur la ligne d intersection.
-// La fonction renvoie False si le point projete est a une distance
-// superieure a Tol du point a projeter.
-//=======================================================================
-Standard_Boolean SingleLine(const gp_Pnt& Psurf,
- const Handle(IntPatch_Line)& lin,
- const Standard_Real Tol,
- Standard_Real& Paraint,
- gp_Vec& Vtgtint)
-{
- IntPatch_IType typarc = lin->ArcType();
-
- Standard_Real parproj = 0.;
- gp_Vec tgint;
- gp_Pnt ptproj;
- Standard_Boolean retvalue;
-
- switch (typarc) {
- case IntPatch_Lin :
- parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf);
- ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Line(),ptproj,tgint);
- break;
- case IntPatch_Circle :
- parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Circle(),Psurf);
- ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Circle(),ptproj,tgint);
- break;
- case IntPatch_Ellipse :
- parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),Psurf);
- ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),ptproj,tgint);
- break;
- case IntPatch_Parabola :
- parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),Psurf);
- ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),ptproj,tgint);
- break;
- case IntPatch_Hyperbola :
- parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),Psurf);
- ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),ptproj,tgint);
- break;
- case IntPatch_Analytic :
- {
- Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
- TColStd_ListOfReal aLParams;
- alin->FindParameter(Psurf, aLParams);
- if (!aLParams.IsEmpty())
- {
- ptproj = Psurf;
- parproj = aLParams.Last();
- gp_Pnt aPtemp;
- if (!alin->D1(parproj, aPtemp, tgint))
- {
- //Previously (before the fix #29807) this code tried to process case
- //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
- //computed Vtgtint input argument value. Currently, any singularities
- //must be processed by high-level algorithms (IntPatch_SpecialPoints class).
- //Therefore this code has been deleted as deprecated.
-
- tgint.SetCoord(0.0, 0.0, 0.0);
- }
- }
- else
- {
- //-- cout << "---- Pb sur ligne analytique dans SingleLine" << endl;
- //-- cout << " Find Parameter"<<endl;
- return Standard_False;
- }
- }
- break;
- case IntPatch_Walking: // impossible . c est pour eviter les warnings
- {
- }
- case IntPatch_Restriction: // impossible . c est pour eviter les warnings
- {
- }
- }
-
- if (Psurf.Distance(ptproj) <= Tol) {
- Paraint = parproj;
- Vtgtint = tgint;
- retvalue = Standard_True;
- }
- else {
- retvalue = Standard_False;
- }
- return retvalue;
-}
-
-
-void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds& listedg,
- IntPatch_SequenceOfLine& slin,
- const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Boolean OnFirst,
- const Standard_Real TolArc) {
-
- Standard_Integer i,j,k;
- Standard_Integer nbedg = listedg.Length();
- Standard_Integer Nblines,Nbpts;
-
- Handle(Adaptor2d_Curve2d) arcRef;
- IntPatch_Point ptvtx, newptvtx;
-
- Handle(IntPatch_RLine) rline; //-- On fait rline = new ... par la suite
-
- IntPatch_TheSegmentOfTheSOnBounds thesegsol;
- IntPatch_ThePathPointOfTheSOnBounds PStartf,PStartl;
- Standard_Boolean dofirst,dolast,procf,procl;
-
- Standard_Real paramf =0.,paraml =0.,U1 =0.,V1 =0.,U2 =0.,V2 =0.;
-
- IntPatch_IType typ;
- IntSurf_TypeTrans trans1,trans2;
- IntSurf_Transition TRest,TArc;
- gp_Vec tgline,norm1,norm2,tgarc;
- gp_Pnt valpt;
-
- gp_Vec d1u,d1v;
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
-
-
- for (i = 1; i <= nbedg; i++) {
- Standard_Boolean EdgeDegenere=Standard_False;
- thesegsol = listedg.Value(i);
- arcRef = thesegsol.Curve();
-
-
- rline = new IntPatch_RLine(Standard_False);
- if(OnFirst) {
- rline->SetArcOnS1(arcRef);
- }
- else {
- rline->SetArcOnS2(arcRef);
- }
-
-// Traitement des points debut/fin du segment solution.
-
- dofirst = Standard_False;
- dolast = Standard_False;
- procf = Standard_False;
- procl = Standard_False;
-
- if (thesegsol.HasFirstPoint()) {
- dofirst = Standard_True;
- PStartf = thesegsol.FirstPoint();
- paramf = PStartf.Parameter();
- }
- if (thesegsol.HasLastPoint()) {
- dolast = Standard_True;
- PStartl = thesegsol.LastPoint();
- paraml = PStartl.Parameter();
- }
-
- if (dofirst && dolast) { // determination de la transition de la ligne
- arcRef->D1(0.5*(paramf+paraml),p2d,d2d);
- if (OnFirst) {
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- else {
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-
- if(d1u.Magnitude()<1e-7) { //-- edge degenere ?
- EdgeDegenere=Standard_True;
- for(Standard_Integer edg=0;edg<=10;edg++) {
- arcRef->D1(paramf+(paraml-paramf)*edg*0.1,p2d,d2d);
- if (OnFirst) {
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- else {
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
-
- if(d1u.Magnitude()>1e-7) {
- EdgeDegenere=Standard_False;
- }
- }
- rline = new IntPatch_RLine(Standard_False);
- if(OnFirst) {
- rline->SetArcOnS1(arcRef);
- }
- else {
- rline->SetArcOnS2(arcRef);
- }
- }
- else {
- norm2 = Quad2.Normale(valpt);
- norm1 = Quad1.Normale(valpt);
-
- if (tgline.DotCross(norm2,norm1) > 0.000000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (tgline.DotCross(norm2,norm1) < -0.000000001){
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1 = trans2 = IntSurf_Undecided;
- }
- rline = new IntPatch_RLine(Standard_False,trans1,trans2);
- if(OnFirst) {
- rline->SetArcOnS1(arcRef);
- }
- else {
- rline->SetArcOnS2(arcRef);
- }
- }
- }
- else {
- rline = new IntPatch_RLine(Standard_False);
- if(OnFirst) {
- rline->SetArcOnS1(arcRef);
- }
- else {
- rline->SetArcOnS2(arcRef);
- }
- }
-
- if (dofirst || dolast) {
- Nblines = slin.Length();
- for (j=1; j<=Nblines; j++) {
- const Handle(IntPatch_Line)& slinj = slin(j);
- typ = slinj->ArcType();
- if (typ == IntPatch_Analytic) {
- Nbpts = Handle(IntPatch_ALine)::DownCast (slinj)->NbVertex();
- }
- else if (typ == IntPatch_Restriction) {
- Nbpts = Handle(IntPatch_RLine)::DownCast (slinj)->NbVertex();
- }
- else {
- Nbpts = Handle(IntPatch_GLine)::DownCast (slinj)->NbVertex();
- }
- for (k=1; k<=Nbpts;k++) {
- if (typ == IntPatch_Analytic) {
- ptvtx = Handle(IntPatch_ALine)::DownCast (slinj)->Vertex(k);
- }
- else if (typ == IntPatch_Restriction) {
- ptvtx = Handle(IntPatch_RLine)::DownCast (slinj)->Vertex(k);
- }
- else {
- ptvtx = Handle(IntPatch_GLine)::DownCast (slinj)->Vertex(k);
- }
-
- if (EdgeDegenere==Standard_False && dofirst) {
- if (ptvtx.Value().Distance(PStartf.Value()) <=TolArc) {
- ptvtx.SetMultiple(Standard_True);
- ptvtx.SetTolerance(TolArc);
- if (typ == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx);
- }
- else if (typ == IntPatch_Restriction) {
- Handle(IntPatch_RLine)::DownCast (slinj)->Replace(k,ptvtx);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,ptvtx);
- }
- newptvtx = ptvtx;
- newptvtx.SetParameter(paramf);
- //Recalcul des transitions si point sur restriction
-
- arcRef->D1(paramf,p2d,d2d);
- if (OnFirst) {
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- else {
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if (ptvtx.IsOnDomS1()) {
- const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS1();
- thearc->D1(ptvtx.ParameterOnArc1(),p2d,d2d);
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm1 = d1u.Crossed(d1v);
- if(norm1.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgline,tgarc,norm1,TRest,TArc);
- }
- newptvtx.SetArc(Standard_True,thearc,ptvtx.ParameterOnArc1(),
- TRest,TArc);
- }
- if (ptvtx.IsOnDomS2()) {
- const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS2();
- thearc->D1(ptvtx.ParameterOnArc2(),p2d,d2d);
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm2 = d1u.Crossed(d1v);
- if(norm2.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgline,tgarc,norm2,TRest,TArc);
- }
- newptvtx.SetArc(Standard_False,thearc,ptvtx.ParameterOnArc2(),
- TRest,TArc);
- }
-
- rline->AddVertex(newptvtx);
- if (!procf){
- procf=Standard_True;
- rline->SetFirstPoint(rline->NbVertex());
- }
- }
- }
- if (EdgeDegenere==Standard_False && dolast) {
- if (ptvtx.Value().Distance(PStartl.Value()) <=TolArc) {
- ptvtx.SetMultiple(Standard_True);
- ptvtx.SetTolerance(TolArc);
- if (typ == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx);
- }
- else if (typ == IntPatch_Restriction) {
- Handle(IntPatch_RLine)::DownCast (slinj)->Replace(k,ptvtx);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,ptvtx);
- }
-
- newptvtx = ptvtx;
- newptvtx.SetParameter(paraml);
- //Recalcul des transitions si point sur restriction
-
- arcRef->D1(paraml,p2d,d2d);
- if (OnFirst) {
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- else {
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- if (ptvtx.IsOnDomS1()) {
- const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS1();
- thearc->D1(ptvtx.ParameterOnArc1(),p2d,d2d);
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm1 = d1u.Crossed(d1v);
- if(norm1.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgline,tgarc,norm1,TRest,TArc);
- }
- newptvtx.SetArc(Standard_True,thearc,ptvtx.ParameterOnArc1(),
- TRest,TArc);
- }
- if (ptvtx.IsOnDomS2()) {
- const Handle(Adaptor2d_Curve2d)& thearc = ptvtx.ArcOnS2();
- thearc->D1(ptvtx.ParameterOnArc2(),p2d,d2d);
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm2 = d1u.Crossed(d1v);
- if(norm2.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgline,tgarc,norm2,TRest,TArc);
- }
- newptvtx.SetArc(Standard_False,thearc,ptvtx.ParameterOnArc2(),
- TRest,TArc);
- }
-
- rline->AddVertex(newptvtx);
- if (!procl){
- procl=Standard_True;
- rline->SetLastPoint(rline->NbVertex());
- }
- }
- }
- }
-// Si on a traite le pt debut et/ou fin, on ne doit pas recommencer si
-// il (ils) correspond(ent) a un point multiple.
-
- if (procf) {
- dofirst = Standard_False;
- }
- if (procl) {
- dolast = Standard_False;
- }
- }
- }
-// Si on n a pas trouve le point debut et./ou fin sur une des lignes
-// d intersection, il faut quand-meme le placer sur la restriction solution
-
- if (dofirst) {
- ptvtx.SetValue(PStartf.Value(),PStartf.Tolerance(),Standard_False);
- Quad1.Parameters(PStartf.Value(),U1,V1);
- Quad2.Parameters(PStartf.Value(),U2,V2);
- ptvtx.SetParameters(U1,V1,U2,V2);
- ptvtx.SetParameter(paramf);
- if (! PStartf.IsNew()) {
- IntSurf_Transition Transline;
- IntSurf_Transition Transarc;
- ptvtx.SetVertex(OnFirst,PStartf.Vertex());
- ptvtx.SetArc(OnFirst,PStartf.Arc(),PStartf.Parameter(),
- Transline,Transarc);
- }
-
- rline->AddVertex(ptvtx);
- rline->SetFirstPoint(rline->NbVertex());
- }
- if (dolast) {
- ptvtx.SetValue(PStartl.Value(),PStartl.Tolerance(),Standard_False);
- Quad1.Parameters(PStartl.Value(),U1,V1);
- Quad2.Parameters(PStartl.Value(),U2,V2);
- ptvtx.SetParameters(U1,V1,U2,V2);
- ptvtx.SetParameter(paraml);
- if (! PStartl.IsNew()) {
- IntSurf_Transition Transline;
- IntSurf_Transition Transarc;
-
- ptvtx.SetVertex(OnFirst,PStartl.Vertex());
- ptvtx.SetArc(OnFirst,PStartl.Arc(),PStartl.Parameter(),
- Transline,Transarc);
- }
-
- rline->AddVertex(ptvtx);
- rline->SetLastPoint(rline->NbVertex());
- }
- slin.Append(rline);
- }
-}
-
-inline const gp_Pnt& PointValue(const Handle(IntPatch_RLine) theRLine,
- const Standard_Integer theIndex)
-{
- return theRLine->Point(theIndex).Value();
-}
-
-inline const gp_Pnt& VertexValue( const Handle(IntPatch_RLine) theRLine,
- const Standard_Integer theIndex)
-{
- return theRLine->Vertex(theIndex).Value();
-}
-
-static Standard_Real SquareDistance(const Handle(IntPatch_GLine)& theGLine,
- const gp_Pnt& theP,
- Extrema_ExtPC& theExtr)
-{
- Standard_Real aSQDist = RealLast();
- switch(theGLine->ArcType())
- {
- case IntPatch_Lin:
- aSQDist = theGLine->Line().SquareDistance(theP);
- break;
- case IntPatch_Circle:
- aSQDist = theGLine->Circle().SquareDistance(theP);
- break;
- default:
- theExtr.Perform(theP);
- if(!theExtr.IsDone() || !theExtr.NbExt())
- {
- //Lines are not overlapped
- return aSQDist;
- }
-
- aSQDist = theExtr.SquareDistance(1);
- const Standard_Integer aNbExtr = theExtr.NbExt();
- for ( Standard_Integer i = 2; i <= aNbExtr; i++)
- {
- const Standard_Real aSQD = theExtr.SquareDistance(i);
- if (aSQD < aSQDist)
- {
- aSQDist = aSQD;
- }
- }
- }
-
- return aSQDist;
-}
-
-static Standard_Boolean IsRLineGood(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Handle(IntPatch_GLine) theGLine,
- const Handle(IntPatch_RLine) theRLine,
- const Standard_Real theTol)
-{
- const Standard_Real aSQTol = theTol*theTol;
- const IntPatch_IType aGType = theGLine->ArcType();
- Standard_Integer aNbPntsM1 = 0;
-
- const gp_Pnt& (*Value) (const Handle(IntPatch_RLine), const Standard_Integer);
-
- if(theRLine->HasPolygon())
- {
- aNbPntsM1 = theRLine->NbPnts()-1;
- Value = PointValue;
- }
- else
- {
- aNbPntsM1 = theRLine->NbVertex()-1;
- Value = VertexValue;
- }
-
- if(aNbPntsM1 < 1)
- return Standard_False;
-
- Extrema_ExtPC anExtr;
- GeomAdaptor_Curve anAC;
- Handle(Geom_Curve) aCurv;
-
- if(aGType == IntPatch_Ellipse)
- aCurv = new Geom_Ellipse(theGLine->Ellipse());
- else if(aGType == IntPatch_Parabola)
- aCurv = new Geom_Parabola(theGLine->Parabola());
- else if(aGType == IntPatch_Hyperbola)
- aCurv = new Geom_Hyperbola(theGLine->Hyperbola());
-
- if(!aCurv.IsNull())
- {
- const Standard_Real anUinf = aCurv->FirstParameter(),
- anUsup = aCurv->LastParameter();
- anAC.Load(aCurv, anUinf, anUsup);
- anExtr.Initialize(anAC, anUinf, anUsup);
- }
-
- if(aNbPntsM1 == 1)
- {
- gp_Pnt aP1(Value(theRLine, 1)), aP2(Value(theRLine, 2));
-
- if(aP1.SquareDistance(aP2) < aSQTol)
- {
- //RLine is degenerated
- return Standard_False;
- }
-
- gp_Pnt aPMid;
- if(theRLine->IsArcOnS1())
- {
- const Handle(Adaptor2d_Curve2d)& anAC2d = theRLine->ArcOnS1();
- const Standard_Real aParF = anAC2d->FirstParameter(),
- aParL = anAC2d->LastParameter();
- gp_Pnt2d aP2d(anAC2d->Value(0.5*(aParF+aParL)));
- aPMid = Quad1.Value(aP2d.X(), aP2d.Y());
- }
- else
- {
- const Handle(Adaptor2d_Curve2d)& anAC2d = theRLine->ArcOnS2();
- const Standard_Real aParF = anAC2d->FirstParameter(),
- aParL = anAC2d->LastParameter();
- gp_Pnt2d aP2d(anAC2d->Value(0.5*(aParF+aParL)));
- aPMid = Quad2.Value(aP2d.X(), aP2d.Y());
- }
-
- const Standard_Real aSQDist = SquareDistance(theGLine, aPMid, anExtr);
- return (aSQDist > aSQTol);
- }
-
- for(Standard_Integer i = 2; i <= aNbPntsM1; i++)
- {
- const gp_Pnt aP(Value(theRLine, i));
- const Standard_Real aSQDist = SquareDistance(theGLine, aP, anExtr);
-
- if(aSQDist > aSQTol)
- return Standard_True;
- }
-
- return Standard_False;
-}
-
-
-void ProcessRLine (IntPatch_SequenceOfLine& slin,
-// const Handle(Adaptor3d_Surface)& Surf1,
-// const Handle(Adaptor3d_Surface)& Surf2,
- const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real _TolArc,
- const Standard_Boolean theIsReqToKeepRLine) {
-
-// On cherche a placer sur les restrictions solutions les points "multiples"
-// des autres lignes d intersection
-// Pas forcemment le plus efficace : on rique de projeter plusieurs fois
-// le meme point sur la meme restriction...
-
- Standard_Real TolArc=100.0*_TolArc;
- if(TolArc>0.1) TolArc=0.1;
-
- Standard_Integer i,j,k;
- Standard_Integer Nblin,Nbvtx, Nbpt;
-
- Standard_Boolean OnFirst = Standard_False,project = Standard_False,keeppoint = Standard_False;
-
- Handle(Adaptor2d_Curve2d) arcref;
- Standard_Real paramproj,paramf,paraml;
-
- TColgp_SequenceOfPnt seq_Pnt3d;
- TColStd_SequenceOfReal seq_Real;
-
- gp_Pnt ptproj,toproj,valpt;
-
- gp_Pnt2d p2d;
- gp_Vec2d d2d;
- gp_Vec d1u,d1v,tgrest,tgarc,norm;
- IntSurf_Transition TRest,TArc;
-#ifndef OCCT_DEBUG
- Standard_Real U =0.,V =0.;
-#else
- Standard_Real U,V;
-#endif
- IntPatch_Point Ptvtx,newptvtx;
-
- IntPatch_IType typ1,typ2;
-
-
- Nblin = slin.Length();
- for (i=1; i<=Nblin; i++) {
- const Handle(IntPatch_Line)& slini = slin(i);
- typ1 = slini->ArcType();
-
- Standard_Boolean HasToDeleteRLine = Standard_False;
- if (typ1 == IntPatch_Restriction) {
- seq_Pnt3d.Clear();
- seq_Real.Clear();
-
- for (j=1; j<=Nblin; j++) {
- const Handle(IntPatch_Line)& slinj = slin(j);
- Nbpt = seq_Pnt3d.Length(); // important que ce soit ici
- typ2 = slinj->ArcType();
- if (typ2 != IntPatch_Restriction) {
- //-- arcref = Handle(IntPatch_RLine)::DownCast (slini)->Arc();
- //-- OnFirst = Handle(IntPatch_RLine)::DownCast (slini)->IsOnFirstSurface();
-
- //-- DES CHOSES A FAIRE ICI
- if(Handle(IntPatch_RLine)::DownCast (slini)->IsArcOnS1()) {
- OnFirst=Standard_True;
- arcref= Handle(IntPatch_RLine)::DownCast (slini)->ArcOnS1();
- }
- else if(Handle(IntPatch_RLine)::DownCast (slini)->IsArcOnS2()) {
- arcref= Handle(IntPatch_RLine)::DownCast (slini)->ArcOnS2();
- OnFirst=Standard_False;
- }
- if (Handle(IntPatch_RLine)::DownCast (slini)->HasFirstPoint()) {
- paramf = Handle(IntPatch_RLine)::DownCast (slini)->FirstPoint().ParameterOnLine();
- }
- else {
- // cout << "Pas de param debut sur rst solution" << endl;
- paramf = RealFirst();
- }
- if (Handle(IntPatch_RLine)::DownCast (slini)->HasLastPoint()) {
- paraml = Handle(IntPatch_RLine)::DownCast (slini)->LastPoint().ParameterOnLine();
- }
- else {
- // cout << "Pas de param debut sur rst solution" << endl;
- paraml = RealLast();
- }
-
- if (typ2 == IntPatch_Analytic) {
- Nbvtx = Handle(IntPatch_ALine)::DownCast (slinj)->NbVertex();
- }
- else {
- Nbvtx = Handle(IntPatch_GLine)::DownCast (slinj)->NbVertex();
- }
-
-
- Standard_Boolean EdgeDegenere=Standard_True;
- for(Standard_Integer edg=0;EdgeDegenere && edg<=10;edg++) {
- arcref->D1(paramf+(paraml-paramf)*edg*0.1,p2d,d2d);
- if (OnFirst) {
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- else {
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- }
- if(d1u.Magnitude()>1e-7) {
- EdgeDegenere=Standard_False;
- }
- }
-
- for (k=1; EdgeDegenere==Standard_False && k<=Nbvtx; k++) {
- if (typ2 == IntPatch_Analytic) {
- Ptvtx = Handle(IntPatch_ALine)::DownCast (slinj)->Vertex(k);
- }
- else {
- Ptvtx = Handle(IntPatch_GLine)::DownCast (slinj)->Vertex(k);
- }
- if ((OnFirst && !Ptvtx.IsOnDomS1()) ||
- (!OnFirst && !Ptvtx.IsOnDomS2())) {
- // Si OnFirst && OnDomS1, c est qu on est a une extremite
- // ca doit etre traite par Process Segment...
- project = Standard_True;
- keeppoint = Standard_False;
- toproj = Ptvtx.Value();
-
- Standard_Integer jj;
- for (jj = 1; jj <= Nbpt; jj++) {
- //for (Standard_Integer jj = 1; jj <= Nbpt; jj++) {
- if (toproj.Distance(seq_Pnt3d(jj)) < _TolArc) {
- project = Standard_False;
- break;
- }
- }
- if (project) { //-- il faut projeter pour trouver le point sur la rline.
- if (OnFirst) {
- Ptvtx.ParametersOnS1(U,V);
- }
- else {
- Ptvtx.ParametersOnS2(U,V);
- }
-
- project = IntPatch_HInterTool::Project(arcref,gp_Pnt2d(U,V),
- paramproj,p2d);
-
- if (project) {
- if (OnFirst) {
- ptproj = Quad1.Value(p2d.X(),p2d.Y());
- }
- else {
- ptproj = Quad2.Value(p2d.X(),p2d.Y());
- }
- if ((toproj.Distance(ptproj) <=100*TolArc) &&
- (paramproj >= paramf) && (paramproj <= paraml)){
- newptvtx = Ptvtx;
- newptvtx.SetParameter(paramproj);
- keeppoint = Standard_True;
- seq_Pnt3d.Append(toproj);
- seq_Real.Append(paramproj);
-
- //-- verifier que si la restriction arcref est trouvee, elle porte ce vertex
- for (int ri=1; ri<=Nblin; ri++) {
- const Handle(IntPatch_Line)& slinri = slin(ri);
- if (slinri->ArcType() == IntPatch_Restriction) {
- if(OnFirst && Handle(IntPatch_RLine)::DownCast (slinri)->IsArcOnS1()) {
- if(arcref == Handle(IntPatch_RLine)::DownCast (slinri)->ArcOnS1()) {
- Handle(IntPatch_RLine)::DownCast (slinri)->AddVertex(newptvtx);
- //printf("\n ImpImpIntersection_0.gxx CAS1 \n");
- }
- }
- else if(OnFirst==Standard_False && Handle(IntPatch_RLine)::DownCast (slinri)->IsArcOnS2()) {
- if(arcref == Handle(IntPatch_RLine)::DownCast (slinri)->ArcOnS2()) {
- Handle(IntPatch_RLine)::DownCast (slinri)->AddVertex(newptvtx);
- //printf("\n ImpImpIntersection_0.gxx CAS2 \n");
- }
- }
- }
- }
- // -- --------------------------------------------------
- }
- }
- }
- else {
- keeppoint = Standard_True;
- newptvtx = Ptvtx;
- newptvtx.SetParameter(seq_Real(jj));
- }
- if (keeppoint) {
- Ptvtx.SetMultiple(Standard_True);
- Ptvtx.SetTolerance(_TolArc);
- newptvtx.SetMultiple(Standard_True);
-
- if (typ2 == IntPatch_Analytic) {
- Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,Ptvtx);
- }
- else {
- Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,Ptvtx);
- }
-
- if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2()) {
-
- arcref->D1(newptvtx.ParameterOnLine(),p2d,d2d);
-
- if (OnFirst) { // donc OnDomS2
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgrest.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-
- const Handle(Adaptor2d_Curve2d)& thearc = Ptvtx.ArcOnS2();
- thearc->D1(Ptvtx.ParameterOnArc2(),p2d,d2d);
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm = d1u.Crossed(d1v); //Quad2.Normale(valpt);
- if(norm.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgrest,tgarc,norm,TRest,TArc);
- }
- newptvtx.SetArc(Standard_False,thearc,
- Ptvtx.ParameterOnArc2(),TRest,TArc);
-
- }
- else { // donc OnDomS1
- Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgrest.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
-
- const Handle(Adaptor2d_Curve2d)& thearc = Ptvtx.ArcOnS1();
- thearc->D1(Ptvtx.ParameterOnArc1(),p2d,d2d);
- Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v);
- tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
- norm = d1u.Crossed(d1v); //Quad1.Normale(valpt);
- if(norm.SquareMagnitude()<1e-16) {
- TRest.SetValue(Standard_True,IntSurf_Undecided);
- TArc.SetValue(Standard_True,IntSurf_Undecided);
- }
- else {
- IntSurf::MakeTransition(tgrest,tgarc,norm,TRest,TArc);
- }
- newptvtx.SetArc(Standard_True,thearc,
- Ptvtx.ParameterOnArc1(),TRest,TArc);
- }
- } //-- if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2())
-
- Handle(IntPatch_RLine)::DownCast (slini)->AddVertex(newptvtx);
-
- } //-- if (keeppoint)
- } //-- if ((OnFirst && !Ptvtx.IsOnDomS1())||(!OnFirst && !Ptvtx.IsOnDomS2()))
- } //-- boucle sur les vertex
-
- if(!theIsReqToKeepRLine)
- {
- Handle(IntPatch_GLine) aGL = Handle(IntPatch_GLine)::DownCast(slinj);
-
- if(!aGL.IsNull())
- {
- HasToDeleteRLine = !IsRLineGood(Quad1, Quad2, aGL,
- Handle(IntPatch_RLine)::DownCast(slini), TolArc);
- }
-
- if(HasToDeleteRLine)
- {
- break;
- }
- }
- } //-- if (typ2 != IntPatch_Restriction)
- } //-- for (j=1; j<=Nblin; j++)
- } //-- if (typ1 == IntPatch_Restriction)
-
- if(HasToDeleteRLine)
- {
- slin.Remove(i);
- i--;
- Nblin = slin.Length();
- continue;
- }
- } //-- for (i=1; i<=Nblin; i++)
-}
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <Bnd_Box2d.hxx>
-
-static Standard_Boolean IntPP (const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Real,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
-
-static Standard_Boolean IntPCy (const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- const Standard_Real H=0.);
-
-
-static Standard_Boolean IntPSp (const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- //modified by NIZNHY-PKV Tue Sep 20 08:59:56 2011t
- const Standard_Real,
- //modified by NIZNHY-PKV Tue Sep 20 08:59:52 2011t
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-
-static Standard_Boolean IntPCo (const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-
-static void ProcessBounds(const Handle(IntPatch_ALine)&,
- const IntPatch_SequenceOfLine&,
- const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- Standard_Boolean&,
- const gp_Pnt&,
- const Standard_Real,
- Standard_Boolean&,
- const gp_Pnt&,
- const Standard_Real,
- Standard_Boolean&,
- const Standard_Real);
-
-
-static
- IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTol3D,
- const Standard_Real theTol2D,
- const Bnd_Box2d& theUVSurf1,
- const Bnd_Box2d& theUVSurf2,
- Standard_Boolean& isTheEmpty,
- Standard_Boolean& isTheSameSurface,
- Standard_Boolean& isTheMultiplePoint,
- IntPatch_SequenceOfLine& theSlin,
- IntPatch_SequenceOfPoint& theSPnt);
-
-static Standard_Boolean IntCySp(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-static Standard_Boolean IntCyCo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-static Standard_Boolean IntSpSp(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-static Standard_Boolean IntCoSp(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-static Standard_Boolean IntCoCo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- Standard_Boolean&,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&,
- IntPatch_SequenceOfPoint&);
-
-//torus
-static Standard_Boolean IntPTo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
-
-static Standard_Boolean IntCyTo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
-
-static Standard_Boolean IntCoTo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
-
-static Standard_Boolean IntSpTo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- const Standard_Boolean,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
-
-static Standard_Boolean IntToTo(const IntSurf_Quadric&,
- const IntSurf_Quadric&,
- const Standard_Real,
- Standard_Boolean&,
- Standard_Boolean&,
- IntPatch_SequenceOfLine&);
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <IntPatch_WLine.hxx>
-
-static
- Standard_Integer SetQuad(const Handle(Adaptor3d_Surface)& theS,
- GeomAbs_SurfaceType& theTS,
- IntSurf_Quadric& theQuad);
-
-//=======================================================================
-//function : IntPatch_ImpImpIntersection
-//purpose :
-//=======================================================================
-IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection ():
-myDone(IntStatus_Fail),
-empt(Standard_True),
-tgte(Standard_False),
-oppo(Standard_False)
-{
-}
-//=======================================================================
-//function : IntPatch_ImpImpIntersection
-//purpose :
-//=======================================================================
-IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection
- (const Handle(Adaptor3d_Surface)& S1,
- const Handle(Adaptor3d_TopolTool)& D1,
- const Handle(Adaptor3d_Surface)& S2,
- const Handle(Adaptor3d_TopolTool)& D2,
- const Standard_Real TolArc,
- const Standard_Real TolTang,
- const Standard_Boolean theIsReqToKeepRLine)
-{
- Perform(S1,D1,S2,D2,TolArc,TolTang, theIsReqToKeepRLine);
-}
-//=======================================================================
-//function : Perform
-//purpose :
-//=======================================================================
-void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_Surface)& S1,
- const Handle(Adaptor3d_TopolTool)& D1,
- const Handle(Adaptor3d_Surface)& S2,
- const Handle(Adaptor3d_TopolTool)& D2,
- const Standard_Real TolArc,
- const Standard_Real TolTang,
- const Standard_Boolean theIsReqToKeepRLine)
-{
- myDone = IntStatus_Fail;
- spnt.Clear();
- slin.Clear();
-
- Standard_Boolean isPostProcessingRequired = Standard_True;
-
- empt = Standard_True;
- tgte = Standard_False;
- oppo = Standard_False;
-
- Standard_Boolean all1 = Standard_False;
- Standard_Boolean all2 = Standard_False;
- Standard_Boolean SameSurf = Standard_False;
- Standard_Boolean multpoint = Standard_False;
-
- Standard_Boolean nosolonS1 = Standard_False;
- // indique s il y a des points sur restriction du carreau 1
- Standard_Boolean nosolonS2 = Standard_False;
- // indique s il y a des points sur restriction du carreau 2
- Standard_Integer i, nbpt, nbseg;
- IntPatch_SequenceOfSegmentOfTheSOnBounds edg1,edg2;
- IntPatch_SequenceOfPathPointOfTheSOnBounds pnt1,pnt2;
- //
- // On commence par intersecter les supports des surfaces
- IntSurf_Quadric quad1, quad2;
- IntPatch_ArcFunction AFunc;
- const Standard_Real Tolang = 1.e-8;
- GeomAbs_SurfaceType typs1, typs2;
- Standard_Boolean bEmpty = Standard_False;
- //
- const Standard_Integer iT1 = SetQuad(S1, typs1, quad1);
- const Standard_Integer iT2 = SetQuad(S2, typs2, quad2);
- //
- if (!iT1 || !iT2) {
- throw Standard_ConstructionError();
- return;
- }
- //
- const Standard_Boolean bReverse = iT1 > iT2;
- const Standard_Integer iTT = iT1*10 + iT2;
- //
- switch (iTT) {
- case 11: { // Plane/Plane
- if (!IntPP(quad1, quad2, Tolang, TolTang, SameSurf, slin)) {
- return;
- }
- break;
- }
- //
- case 12:
- case 21: { // Plane/Cylinder
- Standard_Real VMin, VMax, H;
- //
- const Handle(Adaptor3d_Surface)& aSCyl = bReverse ? S1 : S2;
- VMin = aSCyl->FirstVParameter();
- VMax = aSCyl->LastVParameter();
- H = (Precision::IsNegativeInfinite(VMin) ||
- Precision::IsPositiveInfinite(VMax)) ? 0 : (VMax - VMin);
- //
- if (!IntPCy(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, H)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 13:
- case 31: { // Plane/Cone
- if (!IntPCo(quad1, quad2, Tolang, TolTang, bReverse, empt, multpoint, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 14:
- case 41: { // Plane/Sphere
- if (!IntPSp(quad1, quad2, Tolang, TolTang, bReverse, empt, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 15:
- case 51: { // Plane/Torus
- if (!IntPTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 22:
- { // Cylinder/Cylinder
- Bnd_Box2d aBox1, aBox2;
-
- const Standard_Real aU1f = S1->FirstUParameter();
- Standard_Real aU1l = S1->LastUParameter();
- const Standard_Real aU2f = S2->FirstUParameter();
- Standard_Real aU2l = S2->LastUParameter();
-
- const Standard_Real anUperiod = 2.0*M_PI;
-
- if(aU1l - aU1f > anUperiod)
- aU1l = aU1f + anUperiod;
-
- if(aU2l - aU2f > anUperiod)
- aU2l = aU2f + anUperiod;
-
- aBox1.Add(gp_Pnt2d(aU1f, S1->FirstVParameter()));
- aBox1.Add(gp_Pnt2d(aU1l, S1->LastVParameter()));
- aBox2.Add(gp_Pnt2d(aU2f, S2->FirstVParameter()));
- aBox2.Add(gp_Pnt2d(aU2l, S2->LastVParameter()));
-
- // Resolution is too big if the cylinder radius is
- // too small. Therefore, we shall bind its value above.
- // Here, we use simple constant.
- const Standard_Real a2DTol = Min(1.0e-4, Min( S1->UResolution(TolTang),
- S2->UResolution(TolTang)));
-
- myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2,
- empt, SameSurf, multpoint, slin, spnt);
-
- if (myDone == IntPatch_ImpImpIntersection::IntStatus_Fail)
- {
- return;
- }
-
- bEmpty = empt;
- if(!slin.IsEmpty())
- {
- const Handle(IntPatch_WLine)& aWLine =
- Handle(IntPatch_WLine)::DownCast(slin.Value(1));
-
- if(!aWLine.IsNull())
- {//No geometric solution
- isPostProcessingRequired = Standard_False;
- }
- }
-
- break;
- }
- //
- case 23:
- case 32: { // Cylinder/Cone
- if (!IntCyCo(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 24:
- case 42: { // Cylinder/Sphere
- if (!IntCySp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 25:
- case 52: { // Cylinder/Torus
- if (!IntCyTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 33: { // Cone/Cone
- if (!IntCoCo(quad1, quad2, TolTang, empt, SameSurf, multpoint, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 34:
- case 43: { // Cone/Sphere
- if (!IntCoSp(quad1, quad2, TolTang, bReverse, empt, multpoint, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 35:
- case 53: { // Cone/Torus
- if (!IntCoTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
- return;
- }
- break;
- }
- //
- case 44: { // Sphere/Sphere
- if (!IntSpSp(quad1, quad2, TolTang, empt, SameSurf, slin, spnt)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 45:
- case 54: { // Sphere/Torus
- if (!IntSpTo(quad1, quad2, TolTang, bReverse, empt, slin)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- case 55: { // Torus/Torus
- if (!IntToTo(quad1, quad2, TolTang, SameSurf, empt, slin)) {
- return;
- }
- bEmpty = empt;
- break;
- }
- //
- default: {
- throw Standard_ConstructionError();
- break;
- }
- }
- //
- if (bEmpty) {
- if (myDone == IntStatus_Fail)
- myDone = IntStatus_OK;
-
- return;
- }
- //
-
- if(isPostProcessingRequired)
- {
- if (!SameSurf) {
- AFunc.SetQuadric(quad2);
- AFunc.Set(S1);
-
- solrst.Perform(AFunc, D1, TolArc, TolTang);
- if (!solrst.IsDone()) {
- return;
- }
-
- if (solrst.AllArcSolution() && typs1 == typs2) {
- all1 = Standard_True;
- }
- nbpt = solrst.NbPoints();
- nbseg= solrst.NbSegments();
- for (i = 1; i <= nbpt; i++)
- {
- const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
- pnt1.Append(aPt);
- }
- for (i = 1; i <= nbseg; i++)
- {
- const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
- edg1.Append(aSegm);
- }
- nosolonS1 = (nbpt == 0) && (nbseg == 0);
-
- if (nosolonS1 && all1) { // cas de face sans restrictions
- all1 = Standard_False;
- }
- }//if (!SameSurf) {
- else {
- nosolonS1 = Standard_True;
- }
-
- if (!SameSurf) {
- AFunc.SetQuadric(quad1);
- AFunc.Set(S2);
-
- solrst.Perform(AFunc, D2, TolArc, TolTang);
- if (!solrst.IsDone()) {
- return;
- }
-
- if (solrst.AllArcSolution() && typs1 == typs2) {
- all2 = Standard_True;
- }
-
- nbpt = solrst.NbPoints();
- nbseg= solrst.NbSegments();
- for (i=1; i<= nbpt; i++) {
- const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
- pnt2.Append(aPt);
- }
-
- for (i=1; i<= nbseg; i++) {
- const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
- edg2.Append(aSegm);
- }
-
- nosolonS2 = (nbpt == 0) && (nbseg == 0);
-
- if (nosolonS2 && all2) { // cas de face sans restrictions
- all2 = Standard_False;
- }
- }// if (!SameSurf) {
- else {
- nosolonS2 = Standard_True;
- }
- //
- if (SameSurf || (all1 && all2)) {
- // faces "paralleles" parfaites
- empt = Standard_False;
- tgte = Standard_True;
- slin.Clear();
- spnt.Clear();
-
- gp_Pnt Ptreference;
-
- switch (typs1) {
- case GeomAbs_Plane: {
- Ptreference = (S1->Plane()).Location();
- }
- break;
- case GeomAbs_Cylinder: {
- Ptreference = ElSLib::Value(0.,0.,S1->Cylinder());
- }
- break;
- case GeomAbs_Sphere: {
- Ptreference = ElSLib::Value(M_PI/4.,M_PI/4.,S1->Sphere());
- }
- break;
- case GeomAbs_Cone: {
- Ptreference = ElSLib::Value(0.,10.,S1->Cone());
- }
- break;
- case GeomAbs_Torus: {
- Ptreference = ElSLib::Value(0.,0.,S1->Torus());
- }
- break;
- default:
- break;
- }
- //
- oppo = quad1.Normale(Ptreference).Dot(quad2.Normale(Ptreference)) < 0.0;
- myDone = IntStatus_OK;
- return;
- }// if (SameSurf || (all1 && all2)) {
-
- if (!nosolonS1 || !nosolonS2) {
- empt = Standard_False;
- // C est la qu il faut commencer a bosser...
- PutPointsOnLine(S1,S2,pnt1, slin, Standard_True, D1, quad1,quad2,
- multpoint,TolArc);
-
- PutPointsOnLine(S1,S2,pnt2, slin, Standard_False,D2, quad2,quad1,
- multpoint,TolArc);
-
- if (edg1.Length() != 0) {
- ProcessSegments(edg1,slin,quad1,quad2,Standard_True,TolArc);
- }
-
- if (edg2.Length() != 0) {
- ProcessSegments(edg2,slin,quad1,quad2,Standard_False,TolArc);
- }
-
- if (edg1.Length() !=0 || edg2.Length() !=0) {
- // ProcessRLine(slin,S1,S2,TolArc);
- ProcessRLine(slin,quad1,quad2,TolArc, theIsReqToKeepRLine);
- }
- }//if (!nosolonS1 || !nosolonS2) {
- else {
- empt = ((slin.Length()==0) && (spnt.Length()==0));
- }
- }
-
- Standard_Integer nblin = slin.Length(),
- aNbPnt = spnt.Length();
- //
- //modified by NIZNHY-PKV Tue Sep 06 10:03:35 2011f
- if (aNbPnt) {
- IntPatch_SequenceOfPoint aSIP;
- //
- for(i=1; i<=aNbPnt; ++i) {
- Standard_Real aU1, aV1, aU2, aV2;
- gp_Pnt2d aP2D;
- TopAbs_State aState1, aState2;
- //
- const IntPatch_Point& aIP=spnt(i);
- aIP.Parameters(aU1, aV1, aU2, aV2);
- //
- aP2D.SetCoord(aU1, aV1);
- aState1=D1->Classify(aP2D, TolArc);
- //
- aP2D.SetCoord(aU2, aV2);
- aState2=D2->Classify(aP2D, TolArc);
- //
- if(aState1!=TopAbs_OUT && aState2!=TopAbs_OUT) {
- aSIP.Append(aIP);
- }
- }
- //
- spnt.Clear();
- //
- aNbPnt=aSIP.Length();
- for(i=1; i<=aNbPnt; ++i) {
- const IntPatch_Point& aIP=aSIP(i);
- spnt.Append(aIP);
- }
- //
- }// if (aNbPnt) {
- //modified by NIZNHY-PKV Tue Sep 06 10:18:20 2011t
- //
- for(i=1; i<=nblin; i++) {
- IntPatch_IType thetype = slin.Value(i)->ArcType();
- if( (thetype == IntPatch_Ellipse)
- ||(thetype == IntPatch_Circle)
- ||(thetype == IntPatch_Lin)
- ||(thetype == IntPatch_Parabola)
- ||(thetype == IntPatch_Hyperbola)) {
- Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
- glin->ComputeVertexParameters(TolArc);
- }
- else if(thetype == IntPatch_Analytic) {
- Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(i));
- aligold->ComputeVertexParameters(TolArc);
- }
- else if(thetype == IntPatch_Restriction) {
- Handle(IntPatch_RLine)& rlig = *((Handle(IntPatch_RLine)*)&slin.Value(i));
- rlig->ComputeVertexParameters(TolArc);
- }
- }
- //
- //----------------------------------------------------------------
- //-- On place 2 vertex sur les courbes de GLine qui n en
- //-- contiennent pas.
- for(i=1; i<=nblin; i++) {
- gp_Pnt P;
- IntPatch_Point point;
- Standard_Real u1,v1,u2,v2;
- if(slin.Value(i)->ArcType() == IntPatch_Circle) {
- const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
- if(glin->NbVertex() == 0) {
- gp_Circ Circ = glin->Circle();
- P=ElCLib::Value(0.0,Circ);
- quad1.Parameters(P,u1,v1);
- quad2.Parameters(P,u2,v2);
- point.SetValue(P,TolArc,Standard_False);
- point.SetParameters(u1,v1,u2,v2);
- point.SetParameter(0.0);
- glin->AddVertex(point);
-
- P=ElCLib::Value(0.0,Circ);
- quad1.Parameters(P,u1,v1);
- quad2.Parameters(P,u2,v2);
- point.SetValue(P,TolArc,Standard_False);
- point.SetParameters(u1,v1,u2,v2);
- point.SetParameter(M_PI+M_PI);
- glin->AddVertex(point);
- }
- }
-
- else if(slin.Value(i)->ArcType() == IntPatch_Ellipse) {
- const Handle(IntPatch_GLine)& glin = *((Handle(IntPatch_GLine)*)&slin.Value(i));
- if(glin->NbVertex() == 0) {
- gp_Elips Elips = glin->Ellipse();
- P=ElCLib::Value(0.0,Elips);
- quad1.Parameters(P,u1,v1);
- quad2.Parameters(P,u2,v2);
- point.SetValue(P,TolArc,Standard_False);
- point.SetParameters(u1,v1,u2,v2);
- point.SetParameter(0.0);
- glin->AddVertex(point);
-
- P=ElCLib::Value(0.0,Elips);
- quad1.Parameters(P,u1,v1);
- quad2.Parameters(P,u2,v2);
- point.SetValue(P,TolArc,Standard_False);
- point.SetParameters(u1,v1,u2,v2);
- point.SetParameter(M_PI+M_PI);
- glin->AddVertex(point);
- }
- }
- }
- myDone = IntStatus_OK;
-}
-
-//=======================================================================
-//function : SetQuad
-//purpose :
-//=======================================================================
-Standard_Integer SetQuad(const Handle(Adaptor3d_Surface)& theS,
- GeomAbs_SurfaceType& theTS,
- IntSurf_Quadric& theQuad)
-{
- theTS = theS->GetType();
- Standard_Integer iRet = 0;
- switch (theTS) {
- case GeomAbs_Plane:
- theQuad.SetValue(theS->Plane());
- iRet = 1;
- break;
- case GeomAbs_Cylinder:
- theQuad.SetValue(theS->Cylinder());
- iRet = 2;
- break;
- case GeomAbs_Cone:
- theQuad.SetValue(theS->Cone());
- iRet = 3;
- break;
- case GeomAbs_Sphere:
- theQuad.SetValue(theS->Sphere());
- iRet = 4;
- break;
- case GeomAbs_Torus:
- theQuad.SetValue(theS->Torus());
- iRet = 5;
- break;
- default:
- break;
- }
- //
- return iRet;
-}
-
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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.
-
-//modified by NIZNHY-PKV Thu Sep 15 11:09:12 2011
-static
- void SeamPosition(const gp_Pnt& aPLoc,
- const gp_Ax3& aPos,
- gp_Ax2& aSeamPos);
-static
- void AdjustToSeam (const gp_Cylinder& aQuad,
- gp_Circ& aCirc);
-static
- void AdjustToSeam (const gp_Sphere& aQuad,
- gp_Circ& aCirc,
- const Standard_Real aTolAng);
-static
- void AdjustToSeam (const gp_Cone& aQuad,
- gp_Circ& aCirc);
-static
- void AdjustToSeam (const gp_Torus& aQuad,
- gp_Circ& aCirc);
-//modified by NIZNHY-PKV Thu Sep 15 11:09:13 2011
-
-//=======================================================================
-//function : IntPP
-//purpose :
-// Traitement du cas Plan/Plan
-//=======================================================================
-Standard_Boolean IntPP (const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tolang,
- const Standard_Real TolTang,
- Standard_Boolean& Same,
- IntPatch_SequenceOfLine& slin)
-
-{
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
- gp_Pln pl1(Quad1.Plane());
- gp_Pln pl2(Quad2.Plane());
-
- IntAna_QuadQuadGeo inter(pl1,pl2,Tolang,TolTang);
- if (!inter.IsDone()) {return Standard_False;}
- Same = Standard_False;
- typint = inter.TypeInter();
- if (typint == IntAna_Same) { // cas faces confondues
- Same = Standard_True;
- }
- else if (typint != IntAna_Empty) { // on a une ligne
- gp_Lin linsol = inter.Line(1);
- Standard_Real discri = linsol.Direction().DotCross
- (Quad2.Normale(linsol.Location()),
- Quad1.Normale(linsol.Location()));
-
- if (discri>0.0) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig =
- new IntPatch_GLine (linsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- return Standard_True;
-}
-//=======================================================================
-//function : IntPCy
-//purpose :
-// Traitement du cas Plan/Cylindre et reciproquement
-//=======================================================================
-Standard_Boolean IntPCy (const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tolang,
- const Standard_Real TolTang,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- IntPatch_SequenceOfLine& slin,
- const Standard_Real H)
-
-{
- gp_Pln Pl;
- gp_Cylinder Cy;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
-
- IntAna_QuadQuadGeo inter;
- if (!Reversed) {
- Pl = Quad1.Plane();
- Cy = Quad2.Cylinder();
- }
- else {
- Pl = Quad2.Plane();
- Cy = Quad1.Cylinder();
- }
- inter.Perform(Pl,Cy,Tolang,TolTang,H);
- if (!inter.IsDone()) {return Standard_False;}
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- Empty = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty : {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Line: {
- gp_Lin linsol = inter.Line(1);
- gp_Pnt orig(linsol.Location());
- if (NbSol == 1) { // ligne de tangence
- gp_Vec TestCurvature(orig,Cy.Location());
- gp_Vec Normp,Normcyl;
- if (!Reversed) {
- Normp = Quad1.Normale(orig);
- Normcyl = Quad2.Normale(orig);
- }
- else {
- Normp = Quad2.Normale(orig);
- Normcyl = Quad1.Normale(orig);
- }
-
- IntSurf_Situation situcyl;
- IntSurf_Situation situp;
-
- if (Normp.Dot(TestCurvature) > 0.) {
- situcyl = IntSurf_Outside;
- if (Normp.Dot(Normcyl) > 0.) {
- situp = IntSurf_Inside;
- }
- else {
- situp = IntSurf_Outside;
- }
- }
- else {
- situcyl = IntSurf_Inside;
- if (Normp.Dot(Normcyl) > 0.) {
- situp = IntSurf_Outside;
- }
- else {
- situp = IntSurf_Inside;
- }
- }
- Handle(IntPatch_GLine) glig;
- if (!Reversed) {
- glig = new IntPatch_GLine(linsol, Standard_True, situp, situcyl);
- }
- else {
- glig = new IntPatch_GLine(linsol, Standard_True, situcyl, situp);
- }
- slin.Append(glig);
- }
- else {
- // on a 2 droites. Il faut determiner les transitions
- // de chacune.
-
- if (linsol.Direction().DotCross(Quad2.Normale(orig),
- Quad1.Normale(orig)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig =
- new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- slin.Append(glig);
-
- linsol = inter.Line(2);
- orig = linsol.Location();
-
- if (linsol.Direction().DotCross(Quad2.Normale(orig),
- Quad1.Normale(orig)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- }
- break;
- //
- case IntAna_Circle: {
- gp_Circ cirsol;
- gp_Pnt ptref;
- gp_Vec Tgt;
- //
- cirsol = inter.Circle(1);
- //modified by NIZNHY-PKV Thu Sep 15 11:30:03 2011f
- AdjustToSeam(Cy, cirsol);
- //modified by NIZNHY-PKV Thu Sep 15 11:30:15 2011t
- ElCLib::D1(0.,cirsol,ptref,Tgt);
-
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
- //
- case IntAna_Ellipse: {
- gp_Elips elipsol = inter.Ellipse(1);
- gp_Pnt ptref;
- gp_Vec Tgt;
- ElCLib::D1(0.,elipsol,ptref,Tgt);
-
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
- //
- default: {
- return Standard_False; // on ne doit pas passer ici
- }
- }
- return Standard_True;
-}
-//=======================================================================
-//function : IntPSp
-//purpose :
-// Traitement du cas Plan/Sphere et reciproquement
-//=======================================================================
-Standard_Boolean IntPSp (const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- //modified by NIZNHY-PKV Tue Sep 20 08:59:36 2011f
- const Standard_Real Tolang,
- //modified by NIZNHY-PKV Tue Sep 20 08:59:39 2011t
- const Standard_Real TolTang,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-
-{
- gp_Circ cirsol;
- gp_Pln Pl;
- gp_Sphere Sp;
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
-
- IntAna_QuadQuadGeo inter;
- if (!Reversed) {
- Pl = Quad1.Plane();
- Sp = Quad2.Sphere();
- }
- else {
- Pl = Quad2.Plane();
- Sp = Quad1.Sphere();
- }
- inter.Perform(Pl,Sp);
-
- if (!inter.IsDone()) {return Standard_False;}
-
- typint = inter.TypeInter();
- Empty = Standard_False;
-
- switch (typint) {
- case IntAna_Empty : {
- Empty = Standard_True;
- }
- break;
- //
- case IntAna_Point: {
- gp_Pnt psol = inter.Point(1);
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(psol,TolTang,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
- //
- case IntAna_Circle: {
- cirsol = inter.Circle(1);
- //modified by NIZNHY-PKV Thu Sep 15 11:30:03 2011f
- AdjustToSeam(Sp, cirsol, Tolang);
- //modified by NIZNHY-PKV Thu Sep 15 11:30:15 2011t
- gp_Pnt ptref;
- gp_Vec Tgt;
- ElCLib::D1(0.,cirsol,ptref,Tgt);
-
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
-
- default: {
- return Standard_False; // on ne doit pas passer ici
- }
- }
- return Standard_True;
-}
-//=======================================================================
-//function : IntPCo
-//purpose :
-// Traitement du cas Plan/Cone et reciproquement
-//=======================================================================
-Standard_Boolean IntPCo (const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tolang,
- const Standard_Real TolTang,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-
-{
- gp_Pnt apex;
-
- gp_Pln Pl;
- gp_Cone Co;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
-
- IntAna_QuadQuadGeo inter;
- if (!Reversed) {
- Pl = Quad1.Plane();
- Co = Quad2.Cone();
- apex = Co.Apex();
- }
- else {
- Pl = Quad2.Plane();
- Co = Quad1.Cone();
- apex = Co.Apex();
- }
-
- inter.Perform(Pl,Co,Tolang,TolTang);
- if (!inter.IsDone()) {
- return Standard_False;
- }
- //
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- Empty = Standard_False;
-
- switch (typint) {
- case IntAna_Point: {
- gp_Pnt psol = inter.Point(1);
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(psol,TolTang,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
-
- case IntAna_Line: {
- gp_Lin linsol = inter.Line(1);
- if (linsol.Direction().Dot(Co.Axis().Direction()) <0.) {
- linsol.SetDirection(linsol.Direction().Reversed());
- }
- Standard_Real para = ElCLib::Parameter(linsol, apex);
- gp_Pnt ptbid (ElCLib::Value(para+5.,linsol));
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(apex,U1,V1);
- Quad2.Parameters(apex,U2,V2);
-
- if (NbSol == 1) { // ligne de tangence
- IntPatch_Point ptsol;
- ptsol.SetValue(apex,TolTang,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(para);
- gp_Pnt ptbid2(apex.XYZ() + 5.*Co.Axis().Direction().XYZ());
- gp_Vec TestCurvature(ptbid,ptbid2);
- gp_Vec Normp,Normco;
- if (!Reversed) {
- Normp = Quad1.Normale(ptbid);
- Normco = Quad2.Normale(ptbid);
- }
- else {
- Normp = Quad2.Normale(ptbid);
- Normco = Quad1.Normale(ptbid);
- }
- IntSurf_Situation situco,situco_otherside;
- IntSurf_Situation situp,situp_otherside;
-
- if (Normp.Dot(TestCurvature) > 0.) {
- situco = IntSurf_Outside;
- situco_otherside = IntSurf_Inside;
- if (Normp.Dot(Normco) > 0.) {
- situp = IntSurf_Inside;
- situp_otherside = IntSurf_Outside;
- }
- else {
- situp = IntSurf_Outside;
- situp_otherside = IntSurf_Inside;
- }
- }
- else {
- situco = IntSurf_Inside;
- situco_otherside = IntSurf_Outside;
- if (Normp.Dot(Normco) > 0.) {
- situp = IntSurf_Outside;
- situp_otherside = IntSurf_Inside;
- }
- else {
- situp = IntSurf_Inside;
- situp_otherside = IntSurf_Outside;
- }
- }
- //----------------------------------------------------------
- //-- Apex ---> Cone.Direction
- //--
- Handle(IntPatch_GLine) glig;
- if (!Reversed) {
- glig = new IntPatch_GLine(linsol, Standard_True, situp, situco);
- }
- else {
- glig = new IntPatch_GLine(linsol, Standard_True, situco, situp);
- }
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- //----------------------------------------------------------
- //-- -Cone.Direction <------- Apex
- //--
- linsol.SetDirection(linsol.Direction().Reversed());
- if (!Reversed) {
- glig = new IntPatch_GLine(linsol, Standard_True, situp_otherside, situco_otherside);
- }
- else {
- glig = new IntPatch_GLine(linsol, Standard_True, situco_otherside, situp_otherside);
- }
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- }
- else {
- // on a 2 droites. Il faut determiner les transitions
- // de chacune. On oriente chaque ligne dans le sens
- // de l axe du cone. Les transitions de chaque ligne seront
- // inverses l une de l autre => on ne fait le calcul que sur
- // la premiere.
- if (linsol.Direction().DotCross
- (Quad2.Normale(ptbid),Quad1.Normale(ptbid)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
-
- Multpoint = Standard_True;
- //------------------------------------------- Ligne 1 -------
- IntPatch_Point ptsol;
- ptsol.SetValue(apex,TolTang,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(para);
- ptsol.SetMultiple(Standard_True);
- Handle(IntPatch_GLine) glig;
- glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- //-----------------------------------------------------------
- //-- Other Side : Les transitions restent les memes
- //-- linsol -> -linsol et Quad1(2).N -> -Quad1(2).N
- //--
- linsol.SetDirection(linsol.Direction().Reversed());
- glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- para = ElCLib::Parameter(linsol, apex);
- ptsol.SetParameter(para);
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
-
- //------------------------------------------- Ligne 2 -------
- linsol = inter.Line(2);
- if (linsol.Direction().Dot(Co.Axis().Direction()) <0.) {
- linsol.SetDirection(linsol.Direction().Reversed());
- }
- para = ElCLib::Parameter(linsol, apex);
- ptbid = ElCLib::Value(para+5.,linsol);
- if (linsol.Direction().DotCross
- (Quad2.Normale(ptbid),Quad1.Normale(ptbid)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- ptsol.SetParameter(para);
- glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- para = ElCLib::Parameter(linsol, apex);
- ptsol.SetParameter(para);
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- //-----------------------------------------------------------
- //-- Other Side : Les transitions restent les memes
- //-- linsol -> -linsol et Quad1(2).N -> -Quad1(2).N
- //--
- linsol.SetDirection(linsol.Direction().Reversed());
- glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- para = ElCLib::Parameter(linsol, apex);
- ptsol.SetParameter(para);
- glig->AddVertex(ptsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- }
- }
- break;
-
- case IntAna_Circle: {
- gp_Circ cirsol = inter.Circle(1);
- //modified by NIZNHY-PKV Thu Sep 15 11:34:04 2011f
- AdjustToSeam(Co, cirsol);
- //modified by NIZNHY-PKV Thu Sep 15 11:36:08 2011t
- gp_Pnt ptref;
- gp_Vec Tgt;
- ElCLib::D1(0.,cirsol,ptref,Tgt);
-
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
-
- case IntAna_Ellipse: {
- gp_Elips elipsol = inter.Ellipse(1);
- gp_Pnt ptref;
- gp_Vec Tgt;
- ElCLib::D1(0.,elipsol,ptref,Tgt);
-
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
-
- case IntAna_Parabola: {
- gp_Parab parabsol = inter.Parabola(1);
-
- gp_Vec Tgtorig(parabsol.YAxis().Direction());
- Standard_Real ptran = Tgtorig.DotCross(Quad2.Normale(parabsol.Location()),
- Quad1.Normale(parabsol.Location()));
- if (ptran >0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (ptran <-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(parabsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
-
- case IntAna_Hyperbola: {
- gp_Pnt tophypr;
- gp_Vec Tgttop;
-
- for(Standard_Integer i=1; i<=2; i++) {
- gp_Hypr hyprsol = inter.Hyperbola(i);
- tophypr = ElCLib::Value(hyprsol.MajorRadius(),
- hyprsol.XAxis());
- Tgttop = hyprsol.YAxis().Direction();
- Standard_Real qwe = Tgttop.DotCross(Quad2.Normale(tophypr),
- Quad1.Normale(tophypr));
-
- if (qwe>0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (qwe<-0.00000001){
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(hyprsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- }
- break;
-
- default: {
- return Standard_False;
- }
- }
- return Standard_True;
-}
-//=======================================================================
-//function : IntPTo
-//purpose :
-//=======================================================================
-Standard_Boolean IntPTo(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTolTang,
- const Standard_Boolean bReversed,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- const gp_Pln aPln = bReversed ? theQuad2.Plane() : theQuad1.Plane();
- const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
- //
- IntAna_QuadQuadGeo inter(aPln, aTorus, theTolTang);
- Standard_Boolean bRet = inter.IsDone();
- //
- if (!bRet) {
- return bRet;
- }
- //
- IntAna_ResultType typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- bEmpty = Standard_False;
- //
- switch (typint) {
- case IntAna_Empty :
- bEmpty = Standard_True;
- break;
- //
- case IntAna_Circle : {
- Standard_Integer i;
- IntSurf_TypeTrans trans1, trans2;
- gp_Pnt ptref;
- gp_Vec Tgt;
- //
- for (i = 1; i <= NbSol; ++i) {
- gp_Circ aC = inter.Circle(i);
- if (!aPln.Axis().IsNormal(aTorus.Axis(), Precision::Angular())) {
- AdjustToSeam(aTorus, aC);
- }
- ElCLib::D1(0., aC, ptref, Tgt);
- //
- if (Tgt.DotCross(theQuad2.Normale(ptref),theQuad1.Normale(ptref)) > 0.0) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- //
- Handle(IntPatch_GLine) glig =
- new IntPatch_GLine(aC, Standard_False, trans1, trans2);
- theSeqLin.Append(glig);
- }
- }
- break;
- //
- case IntAna_NoGeometricSolution:
- default:
- bRet = Standard_False;
- break;
- }
- //
- return bRet;
-}
-//
-//modified by NIZNHY-PKV Thu Sep 15 10:53:39 2011f
-//=======================================================================
-//function : AdjustToSeam
-//purpose :
-//=======================================================================
-void AdjustToSeam (const gp_Cone& aQuad,
- gp_Circ& aCirc)
-{
- gp_Ax2 aAx2;
- //
- const gp_Pnt& aPLoc=aCirc.Location();
- const gp_Ax3& aAx3=aQuad.Position();
- SeamPosition(aPLoc, aAx3, aAx2);
- aCirc.SetPosition(aAx2);
-}
-//=======================================================================
-//function : AdjustToSeam
-//purpose :
-//=======================================================================
-void AdjustToSeam (const gp_Sphere& aQuad,
- gp_Circ& aCirc,
- const Standard_Real aTolAng)
-{
- gp_Ax2 aAx2;
- //
- const gp_Ax1& aAx1C=aCirc.Axis();
- const gp_Ax3& aAx3=aQuad.Position();
- const gp_Ax1& aAx1Q=aAx3.Axis();
- //
- const gp_Dir& aDirC=aAx1C.Direction();
- const gp_Dir& aDirQ=aAx1Q.Direction();
- if (aDirC.IsParallel(aDirQ, aTolAng)) {
- const gp_Pnt& aPLoc=aCirc.Location();
- SeamPosition(aPLoc, aAx3, aAx2);
- aCirc.SetPosition(aAx2);
- }
-}
-//=======================================================================
-//function : AdjustToSeam
-//purpose :
-//=======================================================================
-void AdjustToSeam (const gp_Cylinder& aQuad,
- gp_Circ& aCirc)
-{
- gp_Ax2 aAx2;
- //
- const gp_Pnt& aPLoc=aCirc.Location();
- const gp_Ax3& aAx3=aQuad.Position();
- SeamPosition(aPLoc, aAx3, aAx2);
- aCirc.SetPosition(aAx2);
-}
-//=======================================================================
-//function : AdjustToSeam
-//purpose :
-//=======================================================================
-void AdjustToSeam (const gp_Torus& aQuad,
- gp_Circ& aCirc)
-{
- gp_Ax2 aAx2;
- //
- const gp_Pnt& aPLoc=aCirc.Location();
- const gp_Ax3& aAx3=aQuad.Position();
- SeamPosition(aPLoc, aAx3, aAx2);
- aCirc.SetPosition(aAx2);
-}
-//=======================================================================
-//function : SeamPosition
-//purpose :
-//=======================================================================
-void SeamPosition(const gp_Pnt& aPLoc,
- const gp_Ax3& aPos,
- gp_Ax2& aSeamPos)
-{
- const gp_Dir& aDZ=aPos.Direction();
- const gp_Dir& aDX=aPos.XDirection();
- gp_Ax2 aAx2(aPLoc, aDZ, aDX);
- aSeamPos=aAx2;
-}
-
-//modified by NIZNHY-PKV Thu Sep 15 10:53:41 2011t
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <algorithm>
-#include <Bnd_Range.hxx>
-#include <IntAna_ListOfCurve.hxx>
-#include <math_Matrix.hxx>
-#include <NCollection_IncAllocator.hxx>
-#include <Standard_DivideByZero.hxx>
-#include <math_Vector.hxx>
-
-//If Abs(a) <= aNulValue then it is considered that a = 0.
-static const Standard_Real aNulValue = 1.0e-11;
-
-static void ShortCosForm( const Standard_Real theCosFactor,
- const Standard_Real theSinFactor,
- Standard_Real& theCoeff,
- Standard_Real& theAngle);
-//
-static Standard_Boolean ExploreCurve(const gp_Cone& theCo,
- IntAna_Curve& aC,
- const Standard_Real aTol,
- IntAna_ListOfCurve& aLC);
-
-static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
- const Standard_Real theUlTarget,
- Standard_Real& theUGiven,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod,
- const Standard_Boolean theFlForce);
-
-
-class ComputationMethods
-{
- //Every cylinder can be represented by the following equation in parametric form:
- // S(U,V) = L + R*cos(U)*Xd+R*sin(U)*Yd+V*Zd,
- //where location L, directions Xd, Yd and Zd have type gp_XYZ.
-
- //Intersection points between two cylinders can be found from the following system:
- // S1(U1, V1) = S2(U2, V2)
- //or
- // {X01 + R1*cos(U1)*Xx1 + R1*sin(U1)*Yx1 + V1*Zx1 = X02 + R2*cos(U2)*Xx2 + R2*sin(U2)*Yx2 + V2*Zx2
- // {Y01 + R1*cos(U1)*Xy1 + R1*sin(U1)*Yy1 + V1*Zy1 = Y02 + R2*cos(U2)*Xy2 + R2*sin(U2)*Yy2 + V2*Zy2 (1)
- // {Z01 + R1*cos(U1)*Xz1 + R1*sin(U1)*Yz1 + V1*Zz1 = Z02 + R2*cos(U2)*Xz2 + R2*sin(U2)*Yz2 + V2*Zz2
-
- //The formula (1) can be rewritten as follows
- // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1
- // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2 (2)
- // {C13*V1+C23*V2=A13*cos(U1)+B13*sin(U1)+A23*cos(U2)+B23*sin(U2)+D3
-
- //Hereafter we consider that in system
- // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1 (3)
- // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2
- //variables V1 and V2 can be found unambiguously, i.e. determinant
- // |C11 C21|
- // | | != 0
- // |C12 C22|
- //
- //In this case, variables V1 and V2 can be found as follows:
- // {V1 = K11*sin(U1)+K21*sin(U2)+L11*cos(U1)+L21*cos(U2)+M1 = K1*cos(U1-FIV1)+L1*cos(U2-PSIV1)+M1 (4)
- // {V2 = K12*sin(U1)+K22*sin(U2)+L12*cos(U1)+L22*cos(U2)+M2 = K2*cos(U2-FIV2)+L2*cos(U2-PSIV2)+M2
-
- //Having substituted result of (4) to the 3rd equation of (2), we will obtain equation
- // cos(U2-FI2) = B*cos(U1-FI1)+C. (5)
-
- //I.e. when U1 is taken different given values (from domain), correspond U2 value can be computed
- //from equation (5). After that, V1 and V2 can be computed from the system (4) (see
- //CylCylComputeParameters(...) methods).
-
- //It is important to remark that equation (5) (in general) has two solutions: U2=FI2 +/- f(U1).
- //Therefore, we are getting here two intersection lines.
-
-public:
- //Stores equations coefficients
- struct stCoeffsValue
- {
- stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
-
- math_Vector mVecA1;
- math_Vector mVecA2;
- math_Vector mVecB1;
- math_Vector mVecB2;
- math_Vector mVecC1;
- math_Vector mVecC2;
- math_Vector mVecD;
-
- Standard_Real mK21; //sinU2
- Standard_Real mK11; //sinU1
- Standard_Real mL21; //cosU2
- Standard_Real mL11; //cosU1
- Standard_Real mM1; //Free member
-
- Standard_Real mK22; //sinU2
- Standard_Real mK12; //sinU1
- Standard_Real mL22; //cosU2
- Standard_Real mL12; //cosU1
- Standard_Real mM2; //Free member
-
- Standard_Real mK1;
- Standard_Real mL1;
- Standard_Real mK2;
- Standard_Real mL2;
-
- Standard_Real mFIV1;
- Standard_Real mPSIV1;
- Standard_Real mFIV2;
- Standard_Real mPSIV2;
-
- Standard_Real mB;
- Standard_Real mC;
- Standard_Real mFI1;
- Standard_Real mFI2;
- };
-
-
- //! Determines, if U2(U1) function is increasing.
- static Standard_Boolean CylCylMonotonicity(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- const Standard_Real thePeriod,
- Standard_Boolean& theIsIncreasing);
-
- //! Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
- //! esimates the tolerance of U2-computing (estimation result is
- //! assigned to *theDelta value).
- static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theU2,
- Standard_Real* const theDelta = 0);
-
- static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1,
- const Standard_Real theU2,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theV1,
- Standard_Real& theV2);
-
- static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theU2,
- Standard_Real& theV1,
- Standard_Real& theV2);
-
-};
-
-ComputationMethods::stCoeffsValue::stCoeffsValue(const gp_Cylinder& theCyl1,
- const gp_Cylinder& theCyl2):
- mVecA1(-theCyl1.Radius()*theCyl1.XAxis().Direction().XYZ()),
- mVecA2(theCyl2.Radius()*theCyl2.XAxis().Direction().XYZ()),
- mVecB1(-theCyl1.Radius()*theCyl1.YAxis().Direction().XYZ()),
- mVecB2(theCyl2.Radius()*theCyl2.YAxis().Direction().XYZ()),
- mVecC1(theCyl1.Axis().Direction().XYZ()),
- mVecC2(theCyl2.Axis().Direction().XYZ().Reversed()),
- mVecD(theCyl2.Location().XYZ() - theCyl1.Location().XYZ())
-{
- enum CoupleOfEquation
- {
- COENONE = 0,
- COE12 = 1,
- COE23 = 2,
- COE13 = 3
- }aFoundCouple = COENONE;
-
-
- Standard_Real aDetV1V2 = 0.0;
-
- const Standard_Real aDelta1 = mVecC1(1)*mVecC2(2)-mVecC1(2)*mVecC2(1); //1-2
- const Standard_Real aDelta2 = mVecC1(2)*mVecC2(3)-mVecC1(3)*mVecC2(2); //2-3
- const Standard_Real aDelta3 = mVecC1(1)*mVecC2(3)-mVecC1(3)*mVecC2(1); //1-3
- const Standard_Real anAbsD1 = Abs(aDelta1); //1-2
- const Standard_Real anAbsD2 = Abs(aDelta2); //2-3
- const Standard_Real anAbsD3 = Abs(aDelta3); //1-3
-
- if(anAbsD1 >= anAbsD2)
- {
- if(anAbsD3 > anAbsD1)
- {
- aFoundCouple = COE13;
- aDetV1V2 = aDelta3;
- }
- else
- {
- aFoundCouple = COE12;
- aDetV1V2 = aDelta1;
- }
- }
- else
- {
- if(anAbsD3 > anAbsD2)
- {
- aFoundCouple = COE13;
- aDetV1V2 = aDelta3;
- }
- else
- {
- aFoundCouple = COE23;
- aDetV1V2 = aDelta2;
- }
- }
-
- // In point of fact, every determinant (aDelta1, aDelta2 and aDelta3) is
- // cross-product between directions (i.e. sine of angle).
- // If sine is too small then sine is (approx.) equal to angle itself.
- // Therefore, in this case we should compare sine with angular tolerance.
- // This constant is used for check if axes are parallel (see constructor
- // AxeOperator::AxeOperator(...) in IntAna_QuadQuadGeo.cxx file).
- if(Abs(aDetV1V2) < Precision::Angular())
- {
- throw Standard_Failure("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
- }
-
- switch(aFoundCouple)
- {
- case COE12:
- break;
- case COE23:
- {
- math_Vector aVTemp(mVecA1);
- mVecA1(1) = aVTemp(2);
- mVecA1(2) = aVTemp(3);
- mVecA1(3) = aVTemp(1);
-
- aVTemp = mVecA2;
- mVecA2(1) = aVTemp(2);
- mVecA2(2) = aVTemp(3);
- mVecA2(3) = aVTemp(1);
-
- aVTemp = mVecB1;
- mVecB1(1) = aVTemp(2);
- mVecB1(2) = aVTemp(3);
- mVecB1(3) = aVTemp(1);
-
- aVTemp = mVecB2;
- mVecB2(1) = aVTemp(2);
- mVecB2(2) = aVTemp(3);
- mVecB2(3) = aVTemp(1);
-
- aVTemp = mVecC1;
- mVecC1(1) = aVTemp(2);
- mVecC1(2) = aVTemp(3);
- mVecC1(3) = aVTemp(1);
-
- aVTemp = mVecC2;
- mVecC2(1) = aVTemp(2);
- mVecC2(2) = aVTemp(3);
- mVecC2(3) = aVTemp(1);
-
- aVTemp = mVecD;
- mVecD(1) = aVTemp(2);
- mVecD(2) = aVTemp(3);
- mVecD(3) = aVTemp(1);
-
- break;
- }
- case COE13:
- {
- math_Vector aVTemp = mVecA1;
- mVecA1(2) = aVTemp(3);
- mVecA1(3) = aVTemp(2);
-
- aVTemp = mVecA2;
- mVecA2(2) = aVTemp(3);
- mVecA2(3) = aVTemp(2);
-
- aVTemp = mVecB1;
- mVecB1(2) = aVTemp(3);
- mVecB1(3) = aVTemp(2);
-
- aVTemp = mVecB2;
- mVecB2(2) = aVTemp(3);
- mVecB2(3) = aVTemp(2);
-
- aVTemp = mVecC1;
- mVecC1(2) = aVTemp(3);
- mVecC1(3) = aVTemp(2);
-
- aVTemp = mVecC2;
- mVecC2(2) = aVTemp(3);
- mVecC2(3) = aVTemp(2);
-
- aVTemp = mVecD;
- mVecD(2) = aVTemp(3);
- mVecD(3) = aVTemp(2);
-
- break;
- }
- default:
- break;
- }
-
- //------- For V1 (begin)
- //sinU2
- mK21 = (mVecC2(2)*mVecB2(1)-mVecC2(1)*mVecB2(2))/aDetV1V2;
- //sinU1
- mK11 = (mVecC2(2)*mVecB1(1)-mVecC2(1)*mVecB1(2))/aDetV1V2;
- //cosU2
- mL21 = (mVecC2(2)*mVecA2(1)-mVecC2(1)*mVecA2(2))/aDetV1V2;
- //cosU1
- mL11 = (mVecC2(2)*mVecA1(1)-mVecC2(1)*mVecA1(2))/aDetV1V2;
- //Free member
- mM1 = (mVecC2(2)*mVecD(1)-mVecC2(1)*mVecD(2))/aDetV1V2;
- //------- For V1 (end)
-
- //------- For V2 (begin)
- //sinU2
- mK22 = (mVecC1(1)*mVecB2(2)-mVecC1(2)*mVecB2(1))/aDetV1V2;
- //sinU1
- mK12 = (mVecC1(1)*mVecB1(2)-mVecC1(2)*mVecB1(1))/aDetV1V2;
- //cosU2
- mL22 = (mVecC1(1)*mVecA2(2)-mVecC1(2)*mVecA2(1))/aDetV1V2;
- //cosU1
- mL12 = (mVecC1(1)*mVecA1(2)-mVecC1(2)*mVecA1(1))/aDetV1V2;
- //Free member
- mM2 = (mVecC1(1)*mVecD(2)-mVecC1(2)*mVecD(1))/aDetV1V2;
- //------- For V1 (end)
-
- ShortCosForm(mL11, mK11, mK1, mFIV1);
- ShortCosForm(mL21, mK21, mL1, mPSIV1);
- ShortCosForm(mL12, mK12, mK2, mFIV2);
- ShortCosForm(mL22, mK22, mL2, mPSIV2);
-
- const Standard_Real aA1=mVecC1(3)*mK21+mVecC2(3)*mK22-mVecB2(3), //sinU2
- aA2=mVecC1(3)*mL21+mVecC2(3)*mL22-mVecA2(3), //cosU2
- aB1=mVecB1(3)-mVecC1(3)*mK11-mVecC2(3)*mK12, //sinU1
- aB2=mVecA1(3)-mVecC1(3)*mL11-mVecC2(3)*mL12; //cosU1
-
- mC =mVecD(3) - mVecC1(3)*mM1 -mVecC2(3)*mM2; //Free
-
- Standard_Real aA = 0.0;
-
- ShortCosForm(aB2,aB1,mB,mFI1);
- ShortCosForm(aA2,aA1,aA,mFI2);
-
- mB /= aA;
- mC /= aA;
-}
-
-class WorkWithBoundaries
-{
-public:
- enum SearchBoundType
- {
- SearchNONE = 0,
- SearchV1 = 1,
- SearchV2 = 2
- };
-
- struct StPInfo
- {
- StPInfo()
- {
- mySurfID = 0;
- myU1 = RealLast();
- myV1 = RealLast();
- myU2 = RealLast();
- myV2 = RealLast();
- }
-
- //Equal to 0 for 1st surface non-zero for 2nd one.
- Standard_Integer mySurfID;
-
- Standard_Real myU1;
- Standard_Real myV1;
- Standard_Real myU2;
- Standard_Real myV2;
-
- bool operator>(const StPInfo& theOther) const
- {
- return myU1 > theOther.myU1;
- }
-
- bool operator<(const StPInfo& theOther) const
- {
- return myU1 < theOther.myU1;
- }
-
- bool operator==(const StPInfo& theOther) const
- {
- return myU1 == theOther.myU1;
- }
- };
-
- WorkWithBoundaries(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const ComputationMethods::stCoeffsValue& theCoeffs,
- const Bnd_Box2d& theUVSurf1,
- const Bnd_Box2d& theUVSurf2,
- const Standard_Integer theNbWLines,
- const Standard_Real thePeriod,
- const Standard_Real theTol3D,
- const Standard_Real theTol2D,
- const Standard_Boolean isTheReverse) :
- myQuad1(theQuad1), myQuad2(theQuad2), myCoeffs(theCoeffs),
- myUVSurf1(theUVSurf1), myUVSurf2(theUVSurf2), myNbWLines(theNbWLines),
- myPeriod(thePeriod), myTol3D(theTol3D), myTol2D(theTol2D),
- myIsReverse(isTheReverse)
- {
- };
-
- // Returns parameters of system solved while finding
- // intersection line
- const ComputationMethods::stCoeffsValue &SICoeffs() const
- {
- return myCoeffs;
- }
-
- // Returns quadric correspond to the index theIdx.
- const IntSurf_Quadric& GetQSurface(const Standard_Integer theIdx) const
- {
- if (theIdx <= 1)
- return myQuad1;
-
- return myQuad2;
- }
-
- // Returns TRUE in case of reverting surfaces
- Standard_Boolean IsReversed() const
- {
- return myIsReverse;
- }
-
- // Returns 2D-tolerance
- Standard_Real Get2dTolerance() const
- {
- return myTol2D;
- }
-
- // Returns 3D-tolerance
- Standard_Real Get3dTolerance() const
- {
- return myTol3D;
- }
-
- // Returns UV-bounds of 1st surface
- const Bnd_Box2d& UVS1() const
- {
- return myUVSurf1;
- }
-
- // Returns UV-bounds of 2nd surface
- const Bnd_Box2d& UVS2() const
- {
- return myUVSurf2;
- }
-
- void AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
- const Standard_Real theU1,
- const Standard_Real theU1Min,
- const Standard_Real theU2,
- const Standard_Real theV1,
- const Standard_Real theV1Prev,
- const Standard_Real theV2,
- const Standard_Real theV2Prev,
- const Standard_Integer theWLIndex,
- const Standard_Boolean theFlForce,
- Standard_Boolean& isTheFound1,
- Standard_Boolean& isTheFound2) const;
-
- static Standard_Boolean BoundariesComputing(const ComputationMethods::stCoeffsValue &theCoeffs,
- const Standard_Real thePeriod,
- Bnd_Range theURange[]);
-
- void BoundaryEstimation(const gp_Cylinder& theCy1,
- const gp_Cylinder& theCy2,
- Bnd_Range& theOutBoxS1,
- Bnd_Range& theOutBoxS2) const;
-
-protected:
-
- //Solves equation (2) (see declaration of ComputationMethods class) in case,
- //when V1 or V2 (is set by theSBType argument) is known (corresponds to the boundary
- //and equal to theVzad) but U1 is unknown. Computation is made by numeric methods and
- //requires initial values (theVInit, theInitU2 and theInitMainVar).
- Standard_Boolean
- SearchOnVBounds(const SearchBoundType theSBType,
- const Standard_Real theVzad,
- const Standard_Real theVInit,
- const Standard_Real theInitU2,
- const Standard_Real theInitMainVar,
- Standard_Real& theMainVariableValue) const;
-
- const WorkWithBoundaries& operator=(const WorkWithBoundaries&);
-
-private:
- friend class ComputationMethods;
-
- const IntSurf_Quadric& myQuad1;
- const IntSurf_Quadric& myQuad2;
- const ComputationMethods::stCoeffsValue& myCoeffs;
- const Bnd_Box2d& myUVSurf1;
- const Bnd_Box2d& myUVSurf2;
- const Standard_Integer myNbWLines;
- const Standard_Real myPeriod;
- const Standard_Real myTol3D;
- const Standard_Real myTol2D;
- const Standard_Boolean myIsReverse;
-};
-
-static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Handle(IntSurf_LineOn2S)& theLine,
- const ComputationMethods::stCoeffsValue& theCoeffs,
- const Standard_Integer theWLIndex,
- const Standard_Integer theMinNbPoints,
- const Standard_Integer theStartPointOnLine,
- const Standard_Integer theEndPointOnLine,
- const Standard_Real theTol2D,
- const Standard_Real thePeriodOfSurf2,
- const Standard_Boolean isTheReverse);
-
-//=======================================================================
-//function : MinMax
-//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
-// theParMAX = MAX(theParMIN, theParMAX).
-//=======================================================================
-static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
-{
- if(theParMIN > theParMAX)
- {
- const Standard_Real aux = theParMAX;
- theParMAX = theParMIN;
- theParMIN = aux;
- }
-}
-
-//=======================================================================
-//function : ExtremaLineLine
-//purpose : Computes extrema between the given lines. Returns parameters
-// on correspond curve (see correspond method for Extrema_ExtElC class).
-//=======================================================================
-static inline void ExtremaLineLine(const gp_Ax1& theC1,
- const gp_Ax1& theC2,
- const Standard_Real theCosA,
- const Standard_Real theSqSinA,
- Standard_Real& thePar1,
- Standard_Real& thePar2)
-{
- const gp_Dir &aD1 = theC1.Direction(),
- &aD2 = theC2.Direction();
-
- const gp_XYZ aL1L2 = theC2.Location().XYZ() - theC1.Location().XYZ();
- const Standard_Real aD1L = aD1.XYZ().Dot(aL1L2),
- aD2L = aD2.XYZ().Dot(aL1L2);
-
- thePar1 = (aD1L - theCosA * aD2L) / theSqSinA;
- thePar2 = (theCosA * aD1L - aD2L) / theSqSinA;
-}
-
-//=======================================================================
-//function : VBoundaryPrecise
-//purpose : By default, we shall consider, that V1 and V2 will be increased
-// if U1 is increased. But if it is not, new V1set and/or V2set
-// must be computed as [V1current - DeltaV1] (analogically
-// for V2). This function processes this case.
-//=======================================================================
-static void VBoundaryPrecise( const math_Matrix& theMatr,
- const Standard_Real theV1AfterDecrByDelta,
- const Standard_Real theV2AfterDecrByDelta,
- Standard_Real& theV1Set,
- Standard_Real& theV2Set)
-{
- //Now we are going to define if V1 (and V2) increases
- //(or decreases) when U1 will increase.
- const Standard_Integer aNbDim = 3;
- math_Matrix aSyst(1, aNbDim, 1, aNbDim);
-
- aSyst.SetCol(1, theMatr.Col(1));
- aSyst.SetCol(2, theMatr.Col(2));
- aSyst.SetCol(3, theMatr.Col(4));
-
- //We have the system (see comment to StepComputing(...) function)
- // {a11*dV1 + a12*dV2 + a14*dU2 = -a13*dU1
- // {a21*dV1 + a22*dV2 + a24*dU2 = -a23*dU1
- // {a31*dV1 + a32*dV2 + a34*dU2 = -a33*dU1
-
- const Standard_Real aDet = aSyst.Determinant();
-
- aSyst.SetCol(1, theMatr.Col(3));
- const Standard_Real aDet1 = aSyst.Determinant();
-
- aSyst.SetCol(1, theMatr.Col(1));
- aSyst.SetCol(2, theMatr.Col(3));
-
- const Standard_Real aDet2 = aSyst.Determinant();
-
- //Now,
- // dV1 = -dU1*aDet1/aDet
- // dV2 = -dU1*aDet2/aDet
-
- //If U1 is increased then dU1 > 0.
- //If (aDet1/aDet > 0) then dV1 < 0 and
- //V1 will be decreased after increasing U1.
-
- //We have analogical situation with V2-parameter.
-
- if(aDet*aDet1 > 0.0)
- {
- theV1Set = theV1AfterDecrByDelta;
- }
-
- if(aDet*aDet2 > 0.0)
- {
- theV2Set = theV2AfterDecrByDelta;
- }
-}
-
-//=======================================================================
-//function : DeltaU1Computing
-//purpose : Computes new step for U1 parameter.
-//=======================================================================
-static inline
- Standard_Boolean DeltaU1Computing(const math_Matrix& theSyst,
- const math_Vector& theFree,
- Standard_Real& theDeltaU1Found)
-{
- Standard_Real aDet = theSyst.Determinant();
-
- if(Abs(aDet) > aNulValue)
- {
- math_Matrix aSyst1(theSyst);
- aSyst1.SetCol(2, theFree);
-
- theDeltaU1Found = Abs(aSyst1.Determinant()/aDet);
- return Standard_True;
- }
-
- return Standard_False;
-}
-
-//=======================================================================
-//function : StepComputing
-//purpose :
-//
-//Attention!!!:
-// theMatr must have 3*5-dimension strictly.
-// For system
-// {a11*V1+a12*V2+a13*dU1+a14*dU2=b1;
-// {a21*V1+a22*V2+a23*dU1+a24*dU2=b2;
-// {a31*V1+a32*V2+a33*dU1+a34*dU2=b3;
-// theMatr must be following:
-// (a11 a12 a13 a14 b1)
-// (a21 a22 a23 a24 b2)
-// (a31 a32 a33 a34 b3)
-//=======================================================================
-static Standard_Boolean StepComputing(const math_Matrix& theMatr,
- const Standard_Real theV1Cur,
- const Standard_Real theV2Cur,
- const Standard_Real theDeltaV1,
- const Standard_Real theDeltaV2,
- Standard_Real& theDeltaU1Found/*,
- Standard_Real& theDeltaU2Found,
- Standard_Real& theV1Found,
- Standard_Real& theV2Found*/)
-{
-#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
- bool flShow = false;
-
- if(flShow)
- {
- printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
- theMatr(1,1), theMatr(1,2), theMatr(1,3), theMatr(1,4), theMatr(1,5));
- printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
- theMatr(2,1), theMatr(2,2), theMatr(2,3), theMatr(2,4), theMatr(2,5));
- printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
- theMatr(3,1), theMatr(3,2), theMatr(3,3), theMatr(3,4), theMatr(3,5));
- }
-#endif
-
- Standard_Boolean isSuccess = Standard_False;
- theDeltaU1Found/* = theDeltaU2Found*/ = RealLast();
- //theV1Found = theV1set;
- //theV2Found = theV2Set;
- const Standard_Integer aNbDim = 3;
-
- math_Matrix aSyst(1, aNbDim, 1, aNbDim);
- math_Vector aFree(1, aNbDim);
-
- //By default, increasing V1(U1) and V2(U1) functions is
- //considered
- Standard_Real aV1Set = theV1Cur + theDeltaV1,
- aV2Set = theV2Cur + theDeltaV2;
-
- //However, what is indeed?
- VBoundaryPrecise( theMatr, theV1Cur - theDeltaV1,
- theV2Cur - theDeltaV2, aV1Set, aV2Set);
-
- aSyst.SetCol(2, theMatr.Col(3));
- aSyst.SetCol(3, theMatr.Col(4));
-
- for(Standard_Integer i = 0; i < 2; i++)
- {
- if(i == 0)
- {//V1 is known
- aSyst.SetCol(1, theMatr.Col(2));
- aFree.Set(1, aNbDim, theMatr.Col(5)-aV1Set*theMatr.Col(1));
- }
- else
- {//i==1 => V2 is known
- aSyst.SetCol(1, theMatr.Col(1));
- aFree.Set(1, aNbDim, theMatr.Col(5)-aV2Set*theMatr.Col(2));
- }
-
- Standard_Real aNewDU = theDeltaU1Found;
- if(DeltaU1Computing(aSyst, aFree, aNewDU))
- {
- isSuccess = Standard_True;
- if(aNewDU < theDeltaU1Found)
- {
- theDeltaU1Found = aNewDU;
- }
- }
- }
-
- if(!isSuccess)
- {
- aFree = theMatr.Col(5) - aV1Set*theMatr.Col(1) - aV2Set*theMatr.Col(2);
- math_Matrix aSyst1(1, aNbDim, 1, 2);
- aSyst1.SetCol(1, aSyst.Col(2));
- aSyst1.SetCol(2, aSyst.Col(3));
-
- //Now we have overdetermined system.
-
- const Standard_Real aDet1 = theMatr(1,3)*theMatr(2,4) - theMatr(2,3)*theMatr(1,4);
- const Standard_Real aDet2 = theMatr(1,3)*theMatr(3,4) - theMatr(3,3)*theMatr(1,4);
- const Standard_Real aDet3 = theMatr(2,3)*theMatr(3,4) - theMatr(3,3)*theMatr(2,4);
- const Standard_Real anAbsD1 = Abs(aDet1);
- const Standard_Real anAbsD2 = Abs(aDet2);
- const Standard_Real anAbsD3 = Abs(aDet3);
-
- if(anAbsD1 >= anAbsD2)
- {
- if(anAbsD1 >= anAbsD3)
- {
- //Det1
- if(anAbsD1 <= aNulValue)
- return isSuccess;
-
- theDeltaU1Found = Abs(aFree(1)*theMatr(2,4) - aFree(2)*theMatr(1,4))/anAbsD1;
- isSuccess = Standard_True;
- }
- else
- {
- //Det3
- if(anAbsD3 <= aNulValue)
- return isSuccess;
-
- theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
- isSuccess = Standard_True;
- }
- }
- else
- {
- if(anAbsD2 >= anAbsD3)
- {
- //Det2
- if(anAbsD2 <= aNulValue)
- return isSuccess;
-
- theDeltaU1Found = Abs(aFree(1)*theMatr(3,4) - aFree(3)*theMatr(1,4))/anAbsD2;
- isSuccess = Standard_True;
- }
- else
- {
- //Det3
- if(anAbsD3 <= aNulValue)
- return isSuccess;
-
- theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
- isSuccess = Standard_True;
- }
- }
- }
-
- return isSuccess;
-}
-
-//=======================================================================
-//function : ProcessBounds
-//purpose :
-//=======================================================================
-void ProcessBounds(const Handle(IntPatch_ALine)& alig, //-- ligne courante
- const IntPatch_SequenceOfLine& slin,
- const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- Standard_Boolean& procf,
- const gp_Pnt& ptf, //-- Debut Ligne Courante
- const Standard_Real first, //-- Paramf
- Standard_Boolean& procl,
- const gp_Pnt& ptl, //-- Fin Ligne courante
- const Standard_Real last, //-- Paraml
- Standard_Boolean& Multpoint,
- const Standard_Real Tol)
-{
- Standard_Integer j,k;
- Standard_Real U1,V1,U2,V2;
- IntPatch_Point ptsol;
- Standard_Real d;
-
- if (procf && procl) {
- j = slin.Length() + 1;
- }
- else {
- j = 1;
- }
-
-
- //-- On prend les lignes deja enregistrees
-
- while (j <= slin.Length()) {
- if(slin.Value(j)->ArcType() == IntPatch_Analytic) {
- const Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(j));
- k = 1;
-
- //-- On prend les vertex des lignes deja enregistrees
-
- while (k <= aligold->NbVertex()) {
- ptsol = aligold->Vertex(k);
- if (!procf) {
- d=ptf.Distance(ptsol.Value());
- if (d <= Tol) {
- ptsol.SetTolerance(Tol);
- if (!ptsol.IsMultiple()) {
- //-- le point ptsol (de aligold) est declare multiple sur aligold
- Multpoint = Standard_True;
- ptsol.SetMultiple(Standard_True);
- aligold->Replace(k,ptsol);
- }
- ptsol.SetParameter(first);
- alig->AddVertex(ptsol);
- alig->SetFirstPoint(alig->NbVertex());
- procf = Standard_True;
-
- //-- On restore le point avec son parametre sur aligold
- ptsol = aligold->Vertex(k);
-
- }
- }
- if (!procl) {
- if (ptl.Distance(ptsol.Value()) <= Tol) {
- ptsol.SetTolerance(Tol);
- if (!ptsol.IsMultiple()) {
- Multpoint = Standard_True;
- ptsol.SetMultiple(Standard_True);
- aligold->Replace(k,ptsol);
- }
- ptsol.SetParameter(last);
- alig->AddVertex(ptsol);
- alig->SetLastPoint(alig->NbVertex());
- procl = Standard_True;
-
- //-- On restore le point avec son parametre sur aligold
- ptsol = aligold->Vertex(k);
-
- }
- }
- if (procf && procl) {
- k = aligold->NbVertex()+1;
- }
- else {
- k = k+1;
- }
- }
- if (procf && procl) {
- j = slin.Length()+1;
- }
- else {
- j = j+1;
- }
- }
- }
-
- ptsol.SetTolerance(Tol);
- if (!procf && !procl) {
- Quad1.Parameters(ptf,U1,V1);
- Quad2.Parameters(ptf,U2,V2);
- ptsol.SetValue(ptf,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(first);
- if (ptf.Distance(ptl) <= Tol) {
- ptsol.SetMultiple(Standard_True); // a voir
- Multpoint = Standard_True; // a voir de meme
- alig->AddVertex(ptsol);
- alig->SetFirstPoint(alig->NbVertex());
-
- ptsol.SetParameter(last);
- alig->AddVertex(ptsol);
- alig->SetLastPoint(alig->NbVertex());
- }
- else {
- alig->AddVertex(ptsol);
- alig->SetFirstPoint(alig->NbVertex());
- Quad1.Parameters(ptl,U1,V1);
- Quad2.Parameters(ptl,U2,V2);
- ptsol.SetValue(ptl,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(last);
- alig->AddVertex(ptsol);
- alig->SetLastPoint(alig->NbVertex());
- }
- }
- else if (!procf) {
- Quad1.Parameters(ptf,U1,V1);
- Quad2.Parameters(ptf,U2,V2);
- ptsol.SetValue(ptf,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(first);
- alig->AddVertex(ptsol);
- alig->SetFirstPoint(alig->NbVertex());
- }
- else if (!procl) {
- Quad1.Parameters(ptl,U1,V1);
- Quad2.Parameters(ptl,U2,V2);
- ptsol.SetValue(ptl,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- ptsol.SetParameter(last);
- alig->AddVertex(ptsol);
- alig->SetLastPoint(alig->NbVertex());
- }
-}
-
-//=======================================================================
-//function : CyCyAnalyticalIntersect
-//purpose : Checks if intersection curve is analytical (line, circle, ellipse)
-// and returns these curves.
-//=======================================================================
-Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const IntAna_QuadQuadGeo& theInter,
- const Standard_Real Tol,
- Standard_Boolean& Empty,
- Standard_Boolean& Same,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-{
- IntPatch_Point ptsol;
-
- Standard_Integer i;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
-
- gp_Elips elipsol;
- gp_Lin linsol;
-
- gp_Cylinder Cy1(Quad1.Cylinder());
- gp_Cylinder Cy2(Quad2.Cylinder());
-
- typint = theInter.TypeInter();
- Standard_Integer NbSol = theInter.NbSolutions();
- Empty = Standard_False;
- Same = Standard_False;
-
- switch (typint)
- {
- case IntAna_Empty:
- {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Same:
- {
- Same = Standard_True;
- }
- break;
-
- case IntAna_Point:
- {
- gp_Pnt psol(theInter.Point(1));
- ptsol.SetValue(psol,Tol,Standard_True);
-
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol, U1, V1);
- Quad2.Parameters(psol, U2, V2);
-
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
-
- case IntAna_Line:
- {
- gp_Pnt ptref;
- if (NbSol == 1)
- { // Cylinders are tangent to each other by line
- linsol = theInter.Line(1);
- ptref = linsol.Location();
-
- //Radius-vectors
- gp_Dir crb1(gp_Vec(ptref,Cy1.Location()));
- gp_Dir crb2(gp_Vec(ptref,Cy2.Location()));
-
- //outer normal lines
- gp_Vec norm1(Quad1.Normale(ptref));
- gp_Vec norm2(Quad2.Normale(ptref));
- IntSurf_Situation situcyl1;
- IntSurf_Situation situcyl2;
-
- if (crb1.Dot(crb2) < 0.)
- { // centre de courbures "opposes"
- //ATTENTION!!!
- // Normal and Radius-vector of the 1st(!) cylinder
- // is used for judging what the situation of the 2nd(!)
- // cylinder is.
-
- if (norm1.Dot(crb1) > 0.)
- {
- situcyl2 = IntSurf_Inside;
- }
- else
- {
- situcyl2 = IntSurf_Outside;
- }
-
- if (norm2.Dot(crb2) > 0.)
- {
- situcyl1 = IntSurf_Inside;
- }
- else
- {
- situcyl1 = IntSurf_Outside;
- }
- }
- else
- {
- if (Cy1.Radius() < Cy2.Radius())
- {
- if (norm1.Dot(crb1) > 0.)
- {
- situcyl2 = IntSurf_Inside;
- }
- else
- {
- situcyl2 = IntSurf_Outside;
- }
-
- if (norm2.Dot(crb2) > 0.)
- {
- situcyl1 = IntSurf_Outside;
- }
- else
- {
- situcyl1 = IntSurf_Inside;
- }
- }
- else
- {
- if (norm1.Dot(crb1) > 0.)
- {
- situcyl2 = IntSurf_Outside;
- }
- else
- {
- situcyl2 = IntSurf_Inside;
- }
-
- if (norm2.Dot(crb2) > 0.)
- {
- situcyl1 = IntSurf_Inside;
- }
- else
- {
- situcyl1 = IntSurf_Outside;
- }
- }
- }
-
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_True, situcyl1, situcyl2);
- slin.Append(glig);
- }
- else
- {
- for (i=1; i <= NbSol; i++)
- {
- linsol = theInter.Line(i);
- ptref = linsol.Location();
- gp_Vec lsd = linsol.Direction();
-
- //Theoretically, qwe = +/- 1.0.
- Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if (qwe >0.00000001)
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (qwe <-0.00000001)
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1=trans2=IntSurf_Undecided;
- }
-
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- }
- }
- break;
-
- case IntAna_Ellipse:
- {
- gp_Vec Tgt;
- gp_Pnt ptref;
- IntPatch_Point pmult1, pmult2;
-
- elipsol = theInter.Ellipse(1);
-
- gp_Pnt pttang1(ElCLib::Value(0.5*M_PI, elipsol));
- gp_Pnt pttang2(ElCLib::Value(1.5*M_PI, elipsol));
-
- Multpoint = Standard_True;
- pmult1.SetValue(pttang1,Tol,Standard_True);
- pmult2.SetValue(pttang2,Tol,Standard_True);
- pmult1.SetMultiple(Standard_True);
- pmult2.SetMultiple(Standard_True);
-
- Standard_Real oU1,oV1,oU2,oV2;
- Quad1.Parameters(pttang1, oU1, oV1);
- Quad2.Parameters(pttang1, oU2, oV2);
-
- pmult1.SetParameters(oU1,oV1,oU2,oV2);
- Quad1.Parameters(pttang2,oU1,oV1);
- Quad2.Parameters(pttang2,oU2,oV2);
-
- pmult2.SetParameters(oU1,oV1,oU2,oV2);
-
- // on traite la premiere ellipse
-
- //-- Calcul de la Transition de la ligne
- ElCLib::D1(0.,elipsol,ptref,Tgt);
-
- //Theoretically, qwe = +/- |Tgt|.
- Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if (qwe>0.00000001)
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (qwe<-0.00000001)
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1=trans2=IntSurf_Undecided;
- }
-
- //-- Transition calculee au point 0 -> Trans2 , Trans1
- //-- car ici, on devarit calculer en PI
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans2,trans1);
- //
- {
- Standard_Real aU1, aV1, aU2, aV2;
- IntPatch_Point aIP;
- gp_Pnt aP (ElCLib::Value(0., elipsol));
- //
- aIP.SetValue(aP,Tol,Standard_False);
- aIP.SetMultiple(Standard_False);
- //
- Quad1.Parameters(aP, aU1, aV1);
- Quad2.Parameters(aP, aU2, aV2);
-
- aIP.SetParameters(aU1, aV1, aU2, aV2);
- //
- aIP.SetParameter(0.);
- glig->AddVertex(aIP);
- glig->SetFirstPoint(1);
- //
- aIP.SetParameter(2.*M_PI);
- glig->AddVertex(aIP);
- glig->SetLastPoint(2);
- }
- //
- pmult1.SetParameter(0.5*M_PI);
- glig->AddVertex(pmult1);
- //
- pmult2.SetParameter(1.5*M_PI);
- glig->AddVertex(pmult2);
-
- //
- slin.Append(glig);
-
- //-- Transitions calculee au point 0 OK
- //
- // on traite la deuxieme ellipse
- elipsol = theInter.Ellipse(2);
-
- Standard_Real param1 = ElCLib::Parameter(elipsol,pttang1);
- Standard_Real param2 = ElCLib::Parameter(elipsol,pttang2);
- Standard_Real parampourtransition = 0.0;
- if (param1 < param2)
- {
- pmult1.SetParameter(0.5*M_PI);
- pmult2.SetParameter(1.5*M_PI);
- parampourtransition = M_PI;
- }
- else {
- pmult1.SetParameter(1.5*M_PI);
- pmult2.SetParameter(0.5*M_PI);
- parampourtransition = 0.0;
- }
-
- //-- Calcul des transitions de ligne pour la premiere ligne
- ElCLib::D1(parampourtransition,elipsol,ptref,Tgt);
-
- //Theoretically, qwe = +/- |Tgt|.
- qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.00000001)
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe< -0.00000001)
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1=trans2=IntSurf_Undecided;
- }
-
- //-- La transition a ete calculee sur un point de cette ligne
- glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
- //
- {
- Standard_Real aU1, aV1, aU2, aV2;
- IntPatch_Point aIP;
- gp_Pnt aP (ElCLib::Value(0., elipsol));
- //
- aIP.SetValue(aP,Tol,Standard_False);
- aIP.SetMultiple(Standard_False);
- //
-
- Quad1.Parameters(aP, aU1, aV1);
- Quad2.Parameters(aP, aU2, aV2);
-
- aIP.SetParameters(aU1, aV1, aU2, aV2);
- //
- aIP.SetParameter(0.);
- glig->AddVertex(aIP);
- glig->SetFirstPoint(1);
- //
- aIP.SetParameter(2.*M_PI);
- glig->AddVertex(aIP);
- glig->SetLastPoint(2);
- }
- //
- glig->AddVertex(pmult1);
- glig->AddVertex(pmult2);
- //
- slin.Append(glig);
- }
- break;
-
- case IntAna_Parabola:
- case IntAna_Hyperbola:
- throw Standard_Failure("IntCyCy(): Wrong intersection type!");
-
- case IntAna_Circle:
- // Circle is useful when we will work with trimmed surfaces
- // (two cylinders can be tangent by their basises, e.g. circle)
- case IntAna_NoGeometricSolution:
- default:
- return Standard_False;
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : ShortCosForm
-//purpose : Represents theCosFactor*cosA+theSinFactor*sinA as
-// theCoeff*cos(A-theAngle) if it is possibly (all angles are
-// in radians).
-//=======================================================================
-static void ShortCosForm( const Standard_Real theCosFactor,
- const Standard_Real theSinFactor,
- Standard_Real& theCoeff,
- Standard_Real& theAngle)
-{
- theCoeff = sqrt(theCosFactor*theCosFactor+theSinFactor*theSinFactor);
- theAngle = 0.0;
- if(IsEqual(theCoeff, 0.0))
- {
- theAngle = 0.0;
- return;
- }
-
- theAngle = acos(Abs(theCosFactor/theCoeff));
-
- if(theSinFactor > 0.0)
- {
- if(IsEqual(theCosFactor, 0.0))
- {
- theAngle = M_PI/2.0;
- }
- else if(theCosFactor < 0.0)
- {
- theAngle = M_PI-theAngle;
- }
- }
- else if(IsEqual(theSinFactor, 0.0))
- {
- if(theCosFactor < 0.0)
- {
- theAngle = M_PI;
- }
- }
- if(theSinFactor < 0.0)
- {
- if(theCosFactor > 0.0)
- {
- theAngle = 2.0*M_PI-theAngle;
- }
- else if(IsEqual(theCosFactor, 0.0))
- {
- theAngle = 3.0*M_PI/2.0;
- }
- else if(theCosFactor < 0.0)
- {
- theAngle = M_PI+theAngle;
- }
- }
-}
-
-//=======================================================================
-//function : CylCylMonotonicity
-//purpose : Determines, if U2(U1) function is increasing.
-//=======================================================================
-Standard_Boolean ComputationMethods::CylCylMonotonicity(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- const Standard_Real thePeriod,
- Standard_Boolean& theIsIncreasing)
-{
- // U2(U1) = FI2 + (+/-)acos(B*cos(U1 - FI1) + C);
- //Accordingly,
- //Func. U2(X1) = FI2 + X1;
- //Func. X1(X2) = anArccosFactor*X2;
- //Func. X2(X3) = acos(X3);
- //Func. X3(X4) = B*X4 + C;
- //Func. X4(U1) = cos(U1 - FI1).
- //
- //Consequently,
- //U2(X1) is always increasing.
- //X1(X2) is increasing if anArccosFactor > 0.0 and
- //is decreasing otherwise.
- //X2(X3) is always decreasing.
- //Therefore, U2(X3) is decreasing if anArccosFactor > 0.0 and
- //is increasing otherwise.
- //X3(X4) is increasing if B > 0 and is decreasing otherwise.
- //X4(U1) is increasing if U1 - FI1 in [PI, 2*PI) and
- //is decreasing U1 - FI1 in [0, PI) or if (U1 - FI1 == 2PI).
- //After that, we can predict behaviour of U2(U1) function:
- //if it is increasing or decreasing.
-
- //For "+/-" sign. If isPlus == TRUE, "+" is chosen, otherwise, we choose "-".
- Standard_Boolean isPlus = Standard_False;
-
- switch(theWLIndex)
- {
- case 0:
- isPlus = Standard_True;
- break;
- case 1:
- isPlus = Standard_False;
- break;
- default:
- //throw Standard_Failure("Error. Range Error!!!!");
- return Standard_False;
- }
-
- Standard_Real aU1Temp = theU1par - theCoeffs.mFI1;
- InscribePoint(0, thePeriod, aU1Temp, 0.0, thePeriod, Standard_False);
-
- theIsIncreasing = Standard_True;
-
- if(((M_PI - aU1Temp) < RealSmall()) && (aU1Temp < thePeriod))
- {
- theIsIncreasing = Standard_False;
- }
-
- if(theCoeffs.mB < 0.0)
- {
- theIsIncreasing = !theIsIncreasing;
- }
-
- if(!isPlus)
- {
- theIsIncreasing = !theIsIncreasing;
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : CylCylComputeParameters
-//purpose : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
-// estimates the tolerance of U2-computing (estimation result is
-// assigned to *theDelta value).
-//=======================================================================
-Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theU2,
- Standard_Real* const theDelta)
-{
- //This formula is got from some experience and can be changed.
- const Standard_Real aTol0 = Min(10.0*Epsilon(1.0)*theCoeffs.mB, aNulValue);
- const Standard_Real aTol = 1.0 - aTol0;
-
- if(theWLIndex < 0 || theWLIndex > 1)
- return Standard_False;
-
- const Standard_Real aSign = theWLIndex ? -1.0 : 1.0;
-
- Standard_Real anArg = cos(theU1par - theCoeffs.mFI1);
- anArg = theCoeffs.mB*anArg + theCoeffs.mC;
-
- if(anArg >= aTol)
- {
- if(theDelta)
- *theDelta = 0.0;
-
- anArg = 1.0;
- }
- else if(anArg <= -aTol)
- {
- if(theDelta)
- *theDelta = 0.0;
-
- anArg = -1.0;
- }
- else if(theDelta)
- {
- //There is a case, when
- // const double aPar = 0.99999999999721167;
- // const double aFI2 = 2.3593296083566181e-006;
-
- //Then
- // aPar - cos(aFI2) == -5.10703e-015 ==> cos(aFI2) == aPar.
- //Theoretically, in this case
- // aFI2 == +/- acos(aPar).
- //However,
- // acos(aPar) - aFI2 == 2.16362e-009.
- //Error is quite big.
-
- //This error should be estimated. Let use following way, which is based
- //on expanding to Taylor series.
-
- // acos(p)-acos(p+x) = x/sqrt(1-p*p).
-
- //If p == (1-d) (when p > 0) or p == (-1+d) (when p < 0) then
- // acos(p)-acos(p+x) = x/sqrt(d*(2-d)).
-
- //Here always aTol0 <= d <= 1. Max(x) is considered (!) to be equal to aTol0.
- //In this case
- // 8*aTol0 <= acos(p)-acos(p+x) <= sqrt(2/(2-aTol0)-1),
- // because 0 < aTol0 < 1.
- //E.g. when aTol0 = 1.0e-11,
- // 8.0e-11 <= acos(p)-acos(p+x) < 2.24e-6.
-
- const Standard_Real aDelta = Min(1.0-anArg, 1.0+anArg);
- Standard_DivideByZero_Raise_if((aDelta*aDelta < RealSmall()) || (aDelta >= 2.0),
- "IntPatch_ImpImpIntersection_4.gxx, CylCylComputeParameters()");
- *theDelta = aTol0/sqrt(aDelta*(2.0-aDelta));
- }
-
- theU2 = acos(anArg);
- theU2 = theCoeffs.mFI2 + aSign*theU2;
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : CylCylComputeParameters
-//purpose : Computes V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively).
-//=======================================================================
-Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1,
- const Standard_Real theU2,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theV1,
- Standard_Real& theV2)
-{
- theV1 = theCoeffs.mK21 * sin(theU2) +
- theCoeffs.mK11 * sin(theU1) +
- theCoeffs.mL21 * cos(theU2) +
- theCoeffs.mL11 * cos(theU1) + theCoeffs.mM1;
-
- theV2 = theCoeffs.mK22 * sin(theU2) +
- theCoeffs.mK12 * sin(theU1) +
- theCoeffs.mL22 * cos(theU2) +
- theCoeffs.mL12 * cos(theU1) + theCoeffs.mM2;
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : CylCylComputeParameters
-//purpose : Computes U2 (U-parameter of the 2nd cylinder),
-// V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively).
-//=======================================================================
-Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
- const Standard_Integer theWLIndex,
- const stCoeffsValue& theCoeffs,
- Standard_Real& theU2,
- Standard_Real& theV1,
- Standard_Real& theV2)
-{
- if(!CylCylComputeParameters(theU1par, theWLIndex, theCoeffs, theU2))
- return Standard_False;
-
- if(!CylCylComputeParameters(theU1par, theU2, theCoeffs, theV1, theV2))
- return Standard_False;
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : SearchOnVBounds
-//purpose :
-//=======================================================================
-Standard_Boolean WorkWithBoundaries::
- SearchOnVBounds(const SearchBoundType theSBType,
- const Standard_Real theVzad,
- const Standard_Real theVInit,
- const Standard_Real theInitU2,
- const Standard_Real theInitMainVar,
- Standard_Real& theMainVariableValue) const
-{
- const Standard_Integer aNbDim = 3;
- const Standard_Real aMaxError = 4.0*M_PI; // two periods
-
- theMainVariableValue = theInitMainVar;
- const Standard_Real aTol2 = 1.0e-18;
- Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVInit;
-
- //Structure of aMatr:
- // C_{1}*U_{1} & C_{2}*U_{2} & C_{3}*V_{*},
- //where C_{1}, C_{2} and C_{3} are math_Vector.
- math_Matrix aMatr(1, aNbDim, 1, aNbDim);
-
- Standard_Real anError = RealLast();
- Standard_Real anErrorPrev = anError;
- Standard_Integer aNbIter = 0;
- do
- {
- if(++aNbIter > 1000)
- return Standard_False;
-
- const Standard_Real aSinU1 = sin(aMainVarPrev),
- aCosU1 = cos(aMainVarPrev),
- aSinU2 = sin(aU2Prev),
- aCosU2 = cos(aU2Prev);
-
- math_Vector aVecFreeMem = (myCoeffs.mVecA2 * aU2Prev +
- myCoeffs.mVecB2) * aSinU2 -
- (myCoeffs.mVecB2 * aU2Prev -
- myCoeffs.mVecA2) * aCosU2 +
- (myCoeffs.mVecA1 * aMainVarPrev +
- myCoeffs.mVecB1) * aSinU1 -
- (myCoeffs.mVecB1 * aMainVarPrev -
- myCoeffs.mVecA1) * aCosU1 +
- myCoeffs.mVecD;
-
- math_Vector aMSum(1, 3);
-
- switch(theSBType)
- {
- case SearchV1:
- aMatr.SetCol(3, myCoeffs.mVecC2);
- aMSum = myCoeffs.mVecC1 * theVzad;
- aVecFreeMem -= aMSum;
- aMSum += myCoeffs.mVecC2*anOtherVar;
- break;
-
- case SearchV2:
- aMatr.SetCol(3, myCoeffs.mVecC1);
- aMSum = myCoeffs.mVecC2 * theVzad;
- aVecFreeMem -= aMSum;
- aMSum += myCoeffs.mVecC1*anOtherVar;
- break;
-
- default:
- return Standard_False;
- }
-
- aMatr.SetCol(1, myCoeffs.mVecA1 * aSinU1 - myCoeffs.mVecB1 * aCosU1);
- aMatr.SetCol(2, myCoeffs.mVecA2 * aSinU2 - myCoeffs.mVecB2 * aCosU2);
-
- Standard_Real aDetMainSyst = aMatr.Determinant();
-
- if(Abs(aDetMainSyst) < aNulValue)
- {
- return Standard_False;
- }
-
- math_Matrix aM1(aMatr), aM2(aMatr), aM3(aMatr);
- aM1.SetCol(1, aVecFreeMem);
- aM2.SetCol(2, aVecFreeMem);
- aM3.SetCol(3, aVecFreeMem);
-
- const Standard_Real aDetMainVar = aM1.Determinant();
- const Standard_Real aDetVar1 = aM2.Determinant();
- const Standard_Real aDetVar2 = aM3.Determinant();
-
- Standard_Real aDelta = aDetMainVar/aDetMainSyst-aMainVarPrev;
-
- if(Abs(aDelta) > aMaxError)
- return Standard_False;
-
- anError = aDelta*aDelta;
- aMainVarPrev += aDelta;
-
- ///
- aDelta = aDetVar1/aDetMainSyst-aU2Prev;
-
- if(Abs(aDelta) > aMaxError)
- return Standard_False;
-
- anError += aDelta*aDelta;
- aU2Prev += aDelta;
-
- ///
- aDelta = aDetVar2/aDetMainSyst-anOtherVar;
- anError += aDelta*aDelta;
- anOtherVar += aDelta;
-
- if(anError > anErrorPrev)
- {//Method diverges. Keep the best result
- const Standard_Real aSinU1Last = sin(aMainVarPrev),
- aCosU1Last = cos(aMainVarPrev),
- aSinU2Last = sin(aU2Prev),
- aCosU2Last = cos(aU2Prev);
- aMSum -= (myCoeffs.mVecA1*aCosU1Last +
- myCoeffs.mVecB1*aSinU1Last +
- myCoeffs.mVecA2*aCosU2Last +
- myCoeffs.mVecB2*aSinU2Last +
- myCoeffs.mVecD);
- const Standard_Real aSQNorm = aMSum.Norm2();
- return (aSQNorm < aTol2);
- }
- else
- {
- theMainVariableValue = aMainVarPrev;
- }
-
- anErrorPrev = anError;
- }
- while(anError > aTol2);
-
- theMainVariableValue = aMainVarPrev;
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : InscribePoint
-//purpose : If theFlForce==TRUE theUGiven will be changed forcefully
-// even if theUGiven is already inscibed in the boundary
-// (if it is possible; i.e. if new theUGiven is inscribed
-// in the boundary, too).
-//=======================================================================
-Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
- const Standard_Real theUlTarget,
- Standard_Real& theUGiven,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod,
- const Standard_Boolean theFlForce)
-{
- if(Precision::IsInfinite(theUGiven))
- {
- return Standard_False;
- }
-
- if((theUfTarget - theUGiven <= theTol2D) &&
- (theUGiven - theUlTarget <= theTol2D))
- {//it has already inscribed
-
- /*
- Utf U Utl
- + * +
- */
-
- if(theFlForce)
- {
- Standard_Real anUtemp = theUGiven + thePeriod;
- if((theUfTarget - anUtemp <= theTol2D) &&
- (anUtemp - theUlTarget <= theTol2D))
- {
- theUGiven = anUtemp;
- return Standard_True;
- }
-
- anUtemp = theUGiven - thePeriod;
- if((theUfTarget - anUtemp <= theTol2D) &&
- (anUtemp - theUlTarget <= theTol2D))
- {
- theUGiven = anUtemp;
- }
- }
-
- return Standard_True;
- }
-
- const Standard_Real aUf = theUfTarget - theTol2D;
- const Standard_Real aUl = aUf + thePeriod;
-
- theUGiven = ElCLib::InPeriod(theUGiven, aUf, aUl);
-
- return ((theUfTarget - theUGiven <= theTol2D) &&
- (theUGiven - theUlTarget <= theTol2D));
-}
-
-//=======================================================================
-//function : InscribeInterval
-//purpose : Shifts theRange in order to make at least one of its
-// boundary in the range [theUfTarget, theUlTarget]
-//=======================================================================
-static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
- const Standard_Real theUlTarget,
- Bnd_Range &theRange,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod)
-{
- Standard_Real anUpar = 0.0;
- if (!theRange.GetMin(anUpar))
- {
- return Standard_False;
- }
-
- const Standard_Real aDelta = theRange.Delta();
- if(InscribePoint(theUfTarget, theUlTarget, anUpar,
- theTol2D, thePeriod, (Abs(theUlTarget-anUpar) < theTol2D)))
- {
- theRange.SetVoid();
- theRange.Add(anUpar);
- theRange.Add(anUpar + aDelta);
- }
- else
- {
- if (!theRange.GetMax (anUpar))
- {
- return Standard_False;
- }
-
- if(InscribePoint(theUfTarget, theUlTarget, anUpar,
- theTol2D, thePeriod, (Abs(theUfTarget-anUpar) < theTol2D)))
- {
- theRange.SetVoid();
- theRange.Add(anUpar);
- theRange.Add(anUpar - aDelta);
- }
- else
- {
- return Standard_False;
- }
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : ExcludeNearElements
-//purpose : Checks if theArr contains two almost equal elements.
-// If it is true then one of equal elements will be excluded
-// (made infinite).
-// Returns TRUE if at least one element of theArr has been changed.
-//ATTENTION!!!
-// 1. Every not infinite element of theArr is considered to be
-// in [0, T] interval (where T is the period);
-// 2. theArr must be sorted in ascending order.
-//=======================================================================
-static Standard_Boolean ExcludeNearElements(Standard_Real theArr[],
- const Standard_Integer theNOfMembers,
- const Standard_Real theUSurf1f,
- const Standard_Real theUSurf1l,
- const Standard_Real theTol)
-{
- Standard_Boolean aRetVal = Standard_False;
- for(Standard_Integer i = 1; i < theNOfMembers; i++)
- {
- Standard_Real &anA = theArr[i],
- &anB = theArr[i-1];
-
- //Here, anA >= anB
-
- if(Precision::IsInfinite(anA))
- break;
-
- if((anA-anB) < theTol)
- {
- if((anB != 0.0) && (anB != theUSurf1f) && (anB != theUSurf1l))
- anA = (anA + anB)/2.0;
- else
- anA = anB;
-
- //Make this element infinite an forget it
- //(we will not use it in next iterations).
- anB = Precision::Infinite();
- aRetVal = Standard_True;
- }
- }
-
- return aRetVal;
-}
-
-//=======================================================================
-//function : AddPointIntoWL
-//purpose : Surf1 is a surface, whose U-par is variable.
-// If theFlBefore == TRUE then we enable the U1-parameter
-// of the added point to be less than U1-parameter of
-// previously added point (in general U1-parameter is
-// always increased; therefore, this situation is abnormal).
-// If theOnlyCheck==TRUE then no point will be added to theLine.
-//=======================================================================
-static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const ComputationMethods::stCoeffsValue& theCoeffs,
- const Standard_Boolean isTheReverse,
- const Standard_Boolean isThePrecise,
- const gp_Pnt2d& thePntOnSurf1,
- const gp_Pnt2d& thePntOnSurf2,
- const Standard_Real theUfSurf1,
- const Standard_Real theUlSurf1,
- const Standard_Real theUfSurf2,
- const Standard_Real theUlSurf2,
- const Standard_Real theVfSurf1,
- const Standard_Real theVlSurf1,
- const Standard_Real theVfSurf2,
- const Standard_Real theVlSurf2,
- const Standard_Real thePeriodOfSurf1,
- const Handle(IntSurf_LineOn2S)& theLine,
- const Standard_Integer theWLIndex,
- const Standard_Real theTol3D,
- const Standard_Real theTol2D,
- const Standard_Boolean theFlBefore = Standard_False,
- const Standard_Boolean theOnlyCheck = Standard_False)
-{
- //Check if the point is in the domain or can be inscribed in the domain after adjusting.
-
- gp_Pnt aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())),
- aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
-
- Standard_Real aU1par = thePntOnSurf1.X();
-
- // aU1par always increases. Therefore, we must reduce its
- // value in order to continue creation of WLine.
- if(!InscribePoint(theUfSurf1, theUlSurf1, aU1par, theTol2D,
- thePeriodOfSurf1, aU1par > 0.5*(theUfSurf1+theUlSurf1)))
- return Standard_False;
-
- if ((theLine->NbPoints() > 0) &&
- ((theUlSurf1 - theUfSurf1) >= (thePeriodOfSurf1 - theTol2D)) &&
- (((aU1par + thePeriodOfSurf1 - theUlSurf1) <= theTol2D) ||
- ((aU1par - thePeriodOfSurf1 - theUfSurf1) >= theTol2D)))
- {
- // aU1par can be adjusted to both theUlSurf1 and theUfSurf1
- // with equal possibilities. This code fragment allows choosing
- // correct parameter from these two variants.
-
- Standard_Real aU1 = 0.0, aV1 = 0.0;
- if (isTheReverse)
- {
- theLine->Value(theLine->NbPoints()).ParametersOnS2(aU1, aV1);
- }
- else
- {
- theLine->Value(theLine->NbPoints()).ParametersOnS1(aU1, aV1);
- }
-
- const Standard_Real aDelta = aU1 - aU1par;
- if (2.0*Abs(aDelta) > thePeriodOfSurf1)
- {
- aU1par += Sign(thePeriodOfSurf1, aDelta);
- }
- }
-
- Standard_Real aU2par = thePntOnSurf2.X();
- if(!InscribePoint(theUfSurf2, theUlSurf2, aU2par, theTol2D,
- thePeriodOfSurf1, Standard_False))
- return Standard_False;
-
- Standard_Real aV1par = thePntOnSurf1.Y();
- if((aV1par - theVlSurf1 > theTol2D) || (theVfSurf1 - aV1par > theTol2D))
- return Standard_False;
-
- Standard_Real aV2par = thePntOnSurf2.Y();
- if((aV2par - theVlSurf2 > theTol2D) || (theVfSurf2 - aV2par > theTol2D))
- return Standard_False;
-
- //Get intersection point and add it in the WL
- IntSurf_PntOn2S aPnt;
-
- if(isTheReverse)
- {
- aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
- aU2par, aV2par,
- aU1par, aV1par);
- }
- else
- {
- aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
- aU1par, aV1par,
- aU2par, aV2par);
- }
-
- Standard_Integer aNbPnts = theLine->NbPoints();
- if(aNbPnts > 0)
- {
- Standard_Real aUl = 0.0, aVl = 0.0;
- const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
- if(isTheReverse)
- aPlast.ParametersOnS2(aUl, aVl);
- else
- aPlast.ParametersOnS1(aUl, aVl);
-
- if(!theFlBefore && (aU1par <= aUl))
- {
- //Parameter value must be increased if theFlBefore == FALSE.
-
- aU1par += thePeriodOfSurf1;
-
- //The condition is as same as in
- //InscribePoint(...) function
- if((theUfSurf1 - aU1par > theTol2D) ||
- (aU1par - theUlSurf1 > theTol2D))
- {
- //New aU1par is out of target interval.
- //Go back to old value.
-
- return Standard_False;
- }
- }
-
- if (theOnlyCheck)
- return Standard_True;
-
- //theTol2D is minimal step along parameter changed.
- //Therefore, if we apply this minimal step two
- //neighbour points will be always "same". Consequently,
- //we should reduce tolerance for IsSame checking.
- const Standard_Real aDTol = 1.0-Epsilon(1.0);
- if(aPnt.IsSame(aPlast, theTol3D*aDTol, theTol2D*aDTol))
- {
- theLine->RemovePoint(aNbPnts);
- }
- }
-
- if (theOnlyCheck)
- return Standard_True;
-
- theLine->Add(aPnt);
-
- if(!isThePrecise)
- return Standard_True;
-
- //Try to precise existing WLine
- aNbPnts = theLine->NbPoints();
- if(aNbPnts >= 3)
- {
- Standard_Real aU1 = 0.0, aU2 = 0.0, aU3 = 0.0, aV = 0.0;
- if(isTheReverse)
- {
- theLine->Value(aNbPnts).ParametersOnS2(aU3, aV);
- theLine->Value(aNbPnts-1).ParametersOnS2(aU2, aV);
- theLine->Value(aNbPnts-2).ParametersOnS2(aU1, aV);
- }
- else
- {
- theLine->Value(aNbPnts).ParametersOnS1(aU3, aV);
- theLine->Value(aNbPnts-1).ParametersOnS1(aU2, aV);
- theLine->Value(aNbPnts-2).ParametersOnS1(aU1, aV);
- }
-
- const Standard_Real aStepPrev = aU2-aU1;
- const Standard_Real aStep = aU3-aU2;
-
- const Standard_Integer aDeltaStep = RealToInt(aStepPrev/aStep);
-
- if((1 < aDeltaStep) && (aDeltaStep < 2000))
- {
- //Add new points in case of non-uniform distribution of existing points
- SeekAdditionalPoints( theQuad1, theQuad2, theLine,
- theCoeffs, theWLIndex, aDeltaStep, aNbPnts-2,
- aNbPnts-1, theTol2D, thePeriodOfSurf1, isTheReverse);
- }
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : AddBoundaryPoint
-//purpose : Find intersection point on V-boundary.
-//=======================================================================
-void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
- const Standard_Real theU1,
- const Standard_Real theU1Min,
- const Standard_Real theU2,
- const Standard_Real theV1,
- const Standard_Real theV1Prev,
- const Standard_Real theV2,
- const Standard_Real theV2Prev,
- const Standard_Integer theWLIndex,
- const Standard_Boolean theFlForce,
- Standard_Boolean& isTheFound1,
- Standard_Boolean& isTheFound2) const
-{
- Standard_Real aUSurf1f = 0.0, //const
- aUSurf1l = 0.0,
- aVSurf1f = 0.0,
- aVSurf1l = 0.0;
- Standard_Real aUSurf2f = 0.0, //const
- aUSurf2l = 0.0,
- aVSurf2f = 0.0,
- aVSurf2l = 0.0;
-
- myUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
- myUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
-
- const Standard_Integer aSize = 4;
- const Standard_Real anArrVzad[aSize] = {aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l};
-
- StPInfo aUVPoint[aSize];
-
- for(Standard_Integer anIDSurf = 0; anIDSurf < 4; anIDSurf+=2)
- {
- const Standard_Real aVf = (anIDSurf == 0) ? theV1 : theV2,
- aVl = (anIDSurf == 0) ? theV1Prev : theV2Prev;
-
- const SearchBoundType aTS = (anIDSurf == 0) ? SearchV1 : SearchV2;
-
- for(Standard_Integer anIDBound = 0; anIDBound < 2; anIDBound++)
- {
- const Standard_Integer anIndex = anIDSurf+anIDBound;
-
- aUVPoint[anIndex].mySurfID = anIDSurf;
-
- if((Abs(aVf-anArrVzad[anIndex]) > myTol2D) &&
- ((aVf-anArrVzad[anIndex])*(aVl-anArrVzad[anIndex]) > 0.0))
- {
- continue;
- }
-
- //Segment [aVf, aVl] intersects at least one V-boundary (first or last)
- // (in general, case is possible, when aVf > aVl).
-
- // Precise intersection point
- const Standard_Boolean aRes = SearchOnVBounds(aTS, anArrVzad[anIndex],
- (anIDSurf == 0) ? theV2 : theV1,
- theU2, theU1,
- aUVPoint[anIndex].myU1);
-
- // aUVPoint[anIndex].myU1 is considered to be nearer to theU1 than
- // to theU1+/-Period
- if (!aRes || (aUVPoint[anIndex].myU1 >= theU1) ||
- (aUVPoint[anIndex].myU1 < theU1Min))
- {
- //Intersection point is not found or out of the domain
- aUVPoint[anIndex].myU1 = RealLast();
- continue;
- }
- else
- {
- //intersection point is found
-
- Standard_Real &aU1 = aUVPoint[anIndex].myU1,
- &aU2 = aUVPoint[anIndex].myU2,
- &aV1 = aUVPoint[anIndex].myV1,
- &aV2 = aUVPoint[anIndex].myV2;
- aU2 = theU2;
- aV1 = theV1;
- aV2 = theV2;
-
- if(!ComputationMethods::
- CylCylComputeParameters(aU1, theWLIndex, myCoeffs, aU2, aV1, aV2))
- {
- // Found point is wrong
- aU1 = RealLast();
- continue;
- }
-
- //Point on true V-boundary.
- if(aTS == SearchV1)
- aV1 = anArrVzad[anIndex];
- else //if(aTS[anIndex] == SearchV2)
- aV2 = anArrVzad[anIndex];
- }
- }
- }
-
- // Sort with acceding U1-parameter.
- std::sort(aUVPoint, aUVPoint+aSize);
-
- isTheFound1 = isTheFound2 = Standard_False;
-
- //Adding found points on boundary in the WLine.
- for(Standard_Integer i = 0; i < aSize; i++)
- {
- if(aUVPoint[i].myU1 == RealLast())
- break;
-
- if(!AddPointIntoWL(myQuad1, myQuad2, myCoeffs, myIsReverse, Standard_False,
- gp_Pnt2d(aUVPoint[i].myU1, aUVPoint[i].myV1),
- gp_Pnt2d(aUVPoint[i].myU2, aUVPoint[i].myV2),
- aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, myPeriod,
- theWL->Curve(), theWLIndex, myTol3D, myTol2D, theFlForce))
- {
- continue;
- }
-
- if(aUVPoint[i].mySurfID == 0)
- {
- isTheFound1 = Standard_True;
- }
- else
- {
- isTheFound2 = Standard_True;
- }
- }
-}
-
-//=======================================================================
-//function : SeekAdditionalPoints
-//purpose : Inserts additional intersection points between neighbor points.
-// This action is bone with several iterations. During every iteration,
-// new point is inserted in middle of every interval.
-// The process will be finished if NbPoints >= theMinNbPoints.
-//=======================================================================
-static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Handle(IntSurf_LineOn2S)& theLine,
- const ComputationMethods::stCoeffsValue& theCoeffs,
- const Standard_Integer theWLIndex,
- const Standard_Integer theMinNbPoints,
- const Standard_Integer theStartPointOnLine,
- const Standard_Integer theEndPointOnLine,
- const Standard_Real theTol2D,
- const Standard_Real thePeriodOfSurf2,
- const Standard_Boolean isTheReverse)
-{
- if(theLine.IsNull())
- return;
-
- Standard_Integer aNbPoints = theEndPointOnLine - theStartPointOnLine + 1;
-
- Standard_Real aMinDeltaParam = theTol2D;
-
- {
- Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
-
- if(isTheReverse)
- {
- theLine->Value(theStartPointOnLine).ParametersOnS2(u1, v1);
- theLine->Value(theEndPointOnLine).ParametersOnS2(u2, v2);
- }
- else
- {
- theLine->Value(theStartPointOnLine).ParametersOnS1(u1, v1);
- theLine->Value(theEndPointOnLine).ParametersOnS1(u2, v2);
- }
-
- aMinDeltaParam = Max(Abs(u2 - u1)/IntToReal(theMinNbPoints), aMinDeltaParam);
- }
-
- Standard_Integer aLastPointIndex = theEndPointOnLine;
- Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
-
- Standard_Integer aNbPointsPrev = 0;
- do
- {
- aNbPointsPrev = aNbPoints;
- for(Standard_Integer fp = theStartPointOnLine, lp = 0; fp < aLastPointIndex; fp = lp + 1)
- {
- Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
- Standard_Real U1l = 0.0, V1l = 0.0; //last point in 1st suraface
-
- Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
- Standard_Real U2l = 0.0, V2l = 0.0; //last point in 2nd suraface
-
- lp = fp+1;
-
- if(isTheReverse)
- {
- theLine->Value(fp).ParametersOnS2(U1f, V1f);
- theLine->Value(lp).ParametersOnS2(U1l, V1l);
-
- theLine->Value(fp).ParametersOnS1(U2f, V2f);
- theLine->Value(lp).ParametersOnS1(U2l, V2l);
- }
- else
- {
- theLine->Value(fp).ParametersOnS1(U1f, V1f);
- theLine->Value(lp).ParametersOnS1(U1l, V1l);
-
- theLine->Value(fp).ParametersOnS2(U2f, V2f);
- theLine->Value(lp).ParametersOnS2(U2l, V2l);
- }
-
- if(Abs(U1l - U1f) <= aMinDeltaParam)
- {
- //Step is minimal. It is not necessary to divide it.
- continue;
- }
-
- U1prec = 0.5*(U1f+U1l);
-
- if(!ComputationMethods::
- CylCylComputeParameters(U1prec, theWLIndex, theCoeffs, U2prec, V1prec, V2prec))
- {
- continue;
- }
-
- MinMax(U2f, U2l);
- if(!InscribePoint(U2f, U2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False))
- {
- continue;
- }
-
- const gp_Pnt aP1(theQuad1.Value(U1prec, V1prec)), aP2(theQuad2.Value(U2prec, V2prec));
- const gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
-
-#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
- std::cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << std::endl;
-#endif
-
- IntSurf_PntOn2S anIP;
- if(isTheReverse)
- {
- anIP.SetValue(aPInt, U2prec, V2prec, U1prec, V1prec);
- }
- else
- {
- anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
- }
-
- theLine->InsertBefore(lp, anIP);
-
- aNbPoints++;
- aLastPointIndex++;
- }
-
- if(aNbPoints >= theMinNbPoints)
- {
- return;
- }
- } while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev));
-}
-
-//=======================================================================
-//function : BoundariesComputing
-//purpose : Computes true domain of future intersection curve (allows
-// avoiding excess iterations)
-//=======================================================================
-Standard_Boolean WorkWithBoundaries::
- BoundariesComputing(const ComputationMethods::stCoeffsValue &theCoeffs,
- const Standard_Real thePeriod,
- Bnd_Range theURange[])
-{
- //All comments to this method is related to the comment
- //to ComputationMethods class
-
- //So, we have the equation
- // cos(U2-FI2)=B*cos(U1-FI1)+C
- //Evidently,
- // -1 <= B*cos(U1-FI1)+C <= 1
-
- if (theCoeffs.mB > 0.0)
- {
- // -(1+C)/B <= cos(U1-FI1) <= (1-C)/B
-
- if (theCoeffs.mB + Abs(theCoeffs.mC) < -1.0)
- {
- //(1-C)/B < -1 or -(1+C)/B > 1 ==> No solution
-
- return Standard_False;
- }
- else if (theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0)
- {
- //(1-C)/B >= 1 and -(1+C)/B <= -1 ==> U=[0;2*PI]+aFI1
- theURange[0].Add(theCoeffs.mFI1);
- theURange[0].Add(thePeriod + theCoeffs.mFI1);
- }
- else if ((1 + theCoeffs.mC <= theCoeffs.mB) &&
- (theCoeffs.mB <= 1 - theCoeffs.mC))
- {
- //(1-C)/B >= 1 and -(1+C)/B >= -1 ==>
- //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1),
- //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB)
-
- Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- const Standard_Real aDAngle = acos(anArg);
- theURange[0].Add(theCoeffs.mFI1);
- theURange[0].Add(aDAngle + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1);
- theURange[1].Add(thePeriod + theCoeffs.mFI1);
- }
- else if ((1 - theCoeffs.mC <= theCoeffs.mB) &&
- (theCoeffs.mB <= 1 + theCoeffs.mC))
- {
- //(1-C)/B <= 1 and -(1+C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1
- //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB)
-
- Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- const Standard_Real aDAngle = acos(anArg);
- theURange[0].Add(aDAngle + theCoeffs.mFI1);
- theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1);
- }
- else if (theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0)
- {
- //(1-C)/B <= 1 and -(1+C)/B >= -1 ==>
- //(U=[aDAngle1;aDAngle2]+aFI1) ||
- //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
- //where aDAngle1 = acos((1 - myCoeffs.mC) / myCoeffs.mB),
- // aDAngle2 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB).
-
- Standard_Real anArg1 = (1 - theCoeffs.mC) / theCoeffs.mB,
- anArg2 = -(theCoeffs.mC + 1) / theCoeffs.mB;
- if(anArg1 > 1.0)
- anArg1 = 1.0;
- if(anArg1 < -1.0)
- anArg1 = -1.0;
-
- if(anArg2 > 1.0)
- anArg2 = 1.0;
- if(anArg2 < -1.0)
- anArg2 = -1.0;
-
- const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
- //(U=[aDAngle1;aDAngle2]+aFI1) ||
- //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
- theURange[0].Add(aDAngle1 + theCoeffs.mFI1);
- theURange[0].Add(aDAngle2 + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1);
- }
- else
- {
- return Standard_False;
- }
- }
- else if (theCoeffs.mB < 0.0)
- {
- // (1-C)/B <= cos(U1-FI1) <= -(1+C)/B
-
- if (theCoeffs.mB + Abs(theCoeffs.mC) > 1.0)
- {
- // -(1+C)/B < -1 or (1-C)/B > 1 ==> No solutions
- return Standard_False;
- }
- else if (-theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0)
- {
- // -(1+C)/B >= 1 and (1-C)/B <= -1 ==> U=[0;2*PI]+aFI1
- theURange[0].Add(theCoeffs.mFI1);
- theURange[0].Add(thePeriod + theCoeffs.mFI1);
- }
- else if ((-theCoeffs.mC - 1 <= theCoeffs.mB) &&
- (theCoeffs.mB <= theCoeffs.mC - 1))
- {
- // -(1+C)/B >= 1 and (1-C)/B >= -1 ==>
- //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1),
- //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB)
-
- Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- const Standard_Real aDAngle = acos(anArg);
- theURange[0].Add(theCoeffs.mFI1);
- theURange[0].Add(aDAngle + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1);
- theURange[1].Add(thePeriod + theCoeffs.mFI1);
- }
- else if ((theCoeffs.mC - 1 <= theCoeffs.mB) &&
- (theCoeffs.mB <= -theCoeffs.mB - 1))
- {
- // -(1+C)/B <= 1 and (1-C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1,
- //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB).
-
- Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- const Standard_Real aDAngle = acos(anArg);
- theURange[0].Add(aDAngle + theCoeffs.mFI1);
- theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1);
- }
- else if (-theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0)
- {
- // -(1+C)/B <= 1 and (1-C)/B >= -1 ==>
- //(U=[aDAngle1;aDAngle2]+aFI1) || (U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1),
- //where aDAngle1 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB),
- // aDAngle2 = acos((1 - myCoeffs.mC) / myCoeffs.mB)
-
- Standard_Real anArg1 = -(theCoeffs.mC + 1) / theCoeffs.mB,
- anArg2 = (1 - theCoeffs.mC) / theCoeffs.mB;
- if(anArg1 > 1.0)
- anArg1 = 1.0;
- if(anArg1 < -1.0)
- anArg1 = -1.0;
-
- if(anArg2 > 1.0)
- anArg2 = 1.0;
- if(anArg2 < -1.0)
- anArg2 = -1.0;
-
- const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
- theURange[0].Add(aDAngle1 + theCoeffs.mFI1);
- theURange[0].Add(aDAngle2 + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1);
- theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1);
- }
- else
- {
- return Standard_False;
- }
- }
- else
- {
- return Standard_False;
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : CriticalPointsComputing
-//purpose : theNbCritPointsMax contains true number of critical points.
-// It must be initialized correctly before function calling
-//=======================================================================
-static void CriticalPointsComputing(const ComputationMethods::stCoeffsValue& theCoeffs,
- const Standard_Real theUSurf1f,
- const Standard_Real theUSurf1l,
- const Standard_Real theUSurf2f,
- const Standard_Real theUSurf2l,
- const Standard_Real thePeriod,
- const Standard_Real theTol2D,
- Standard_Integer& theNbCritPointsMax,
- Standard_Real theU1crit[])
-{
- //[0...1] - in these points parameter U1 goes through
- // the seam-edge of the first cylinder.
- //[2...3] - First and last U1 parameter.
- //[4...5] - in these points parameter U2 goes through
- // the seam-edge of the second cylinder.
- //[6...9] - in these points an intersection line goes through
- // U-boundaries of the second surface.
- //[10...11] - Boundary of monotonicity interval of U2(U1) function
- // (see CylCylMonotonicity() function)
-
- theU1crit[0] = 0.0;
- theU1crit[1] = thePeriod;
- theU1crit[2] = theUSurf1f;
- theU1crit[3] = theUSurf1l;
-
- const Standard_Real aCOS = cos(theCoeffs.mFI2);
- const Standard_Real aBSB = Abs(theCoeffs.mB);
- if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
- {
- Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
- theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
- }
-
- Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
- Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
- MinMax(aSf, aSl);
-
- //In accorance with pure mathematic, theU1crit[6] and [8]
- //must be -Precision::Infinite() instead of used +Precision::Infinite()
- theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
- -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
- Precision::Infinite();
- theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
- -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
- Precision::Infinite();
- theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
- acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
- Precision::Infinite();
- theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
- acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
- Precision::Infinite();
-
- theU1crit[10] = theCoeffs.mFI1;
- theU1crit[11] = M_PI+theCoeffs.mFI1;
-
- //preparative treatment of array. This array must have faled to contain negative
- //infinity number
-
- for(Standard_Integer i = 0; i < theNbCritPointsMax; i++)
- {
- if(Precision::IsInfinite(theU1crit[i]))
- {
- continue;
- }
-
- theU1crit[i] = fmod(theU1crit[i], thePeriod);
- if(theU1crit[i] < 0.0)
- theU1crit[i] += thePeriod;
- }
-
- //Here all not infinite elements of theU1crit are in [0, thePeriod) range
-
- do
- {
- std::sort(theU1crit, theU1crit + theNbCritPointsMax);
- }
- while(ExcludeNearElements(theU1crit, theNbCritPointsMax,
- theUSurf1f, theUSurf1l, theTol2D));
-
- //Here all not infinite elements in theU1crit are different and sorted.
-
- while(theNbCritPointsMax > 0)
- {
- Standard_Real &anB = theU1crit[theNbCritPointsMax-1];
- if(Precision::IsInfinite(anB))
- {
- theNbCritPointsMax--;
- continue;
- }
-
- //1st not infinte element is found
-
- if(theNbCritPointsMax == 1)
- break;
-
- //Here theNbCritPointsMax > 1
-
- Standard_Real &anA = theU1crit[0];
-
- //Compare 1st and last significant elements of theU1crit
- //They may still differs by period.
-
- if (Abs(anB - anA - thePeriod) < theTol2D)
- {//E.g. anA == 2.0e-17, anB == (thePeriod-1.0e-18)
- anA = (anA + anB - thePeriod)/2.0;
- anB = Precision::Infinite();
- theNbCritPointsMax--;
- }
-
- //Out of "while(theNbCritPointsMax > 0)" cycle.
- break;
- }
-
- //Attention! Here theU1crit may be unsorted.
-}
-
-//=======================================================================
-//function : BoundaryEstimation
-//purpose : Rough estimation of the parameter range.
-//=======================================================================
-void WorkWithBoundaries::BoundaryEstimation(const gp_Cylinder& theCy1,
- const gp_Cylinder& theCy2,
- Bnd_Range& theOutBoxS1,
- Bnd_Range& theOutBoxS2) const
-{
- const gp_Dir &aD1 = theCy1.Axis().Direction(),
- &aD2 = theCy2.Axis().Direction();
- const Standard_Real aR1 = theCy1.Radius(),
- aR2 = theCy2.Radius();
-
- //Let consider a parallelogram. Its edges are parallel to aD1 and aD2.
- //Its altitudes are equal to 2*aR1 and 2*aR2 (diameters of the cylinders).
- //In fact, this parallelogram is a projection of the cylinders to the plane
- //created by the intersected axes aD1 and aD2 (if the axes are skewed then
- //one axis can be translated by parallel shifting till intersection).
-
- const Standard_Real aCosA = aD1.Dot(aD2);
- const Standard_Real aSqSinA = aD1.XYZ().CrossSquareMagnitude(aD2.XYZ());
-
- //If sine is small then it can be compared with angle.
- if (aSqSinA < Precision::Angular()*Precision::Angular())
- return;
-
- //Half of delta V. Delta V is a distance between
- //projections of two opposite parallelogram vertices
- //(joined by the maximal diagonal) to the cylinder axis.
- const Standard_Real aSinA = sqrt(aSqSinA);
- const Standard_Real anAbsCosA = Abs(aCosA);
- const Standard_Real aHDV1 = (aR1 * anAbsCosA + aR2) / aSinA,
- aHDV2 = (aR2 * anAbsCosA + aR1) / aSinA;
-
-#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
- //The code in this block is created for test only.It is stupidly to create
- //OCCT-test for the method, which will be changed possibly never.
- std::cout << "Reference values: aHDV1 = " << aHDV1 << "; aHDV2 = " << aHDV2 << std::endl;
-#endif
-
- //V-parameters of intersection point of the axes (in case of skewed axes,
- //see comment above).
- Standard_Real aV01 = 0.0, aV02 = 0.0;
- ExtremaLineLine(theCy1.Axis(), theCy2.Axis(), aCosA, aSqSinA, aV01, aV02);
-
- theOutBoxS1.Add(aV01 - aHDV1);
- theOutBoxS1.Add(aV01 + aHDV1);
-
- theOutBoxS2.Add(aV02 - aHDV2);
- theOutBoxS2.Add(aV02 + aHDV2);
-
- theOutBoxS1.Enlarge(Precision::Confusion());
- theOutBoxS2.Enlarge(Precision::Confusion());
-
- Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
- myUVSurf1.Get(aU1, aV1, aU2, aV2);
- theOutBoxS1.Common(Bnd_Range(aV1, aV2));
-
- myUVSurf2.Get(aU1, aV1, aU2, aV2);
- theOutBoxS2.Common(Bnd_Range(aV1, aV2));
-}
-
-//=======================================================================
-//function : CyCyNoGeometric
-//purpose :
-//=======================================================================
-static IntPatch_ImpImpIntersection::IntStatus
- CyCyNoGeometric(const gp_Cylinder &theCyl1,
- const gp_Cylinder &theCyl2,
- const WorkWithBoundaries &theBW,
- Bnd_Range theRange[],
- const Standard_Integer theNbOfRanges /*=2*/,
- Standard_Boolean& isTheEmpty,
- IntPatch_SequenceOfLine& theSlin,
- IntPatch_SequenceOfPoint& theSPnt)
-{
- Standard_Real aUSurf1f = 0.0, aUSurf1l = 0.0,
- aUSurf2f = 0.0, aUSurf2l = 0.0,
- aVSurf1f = 0.0, aVSurf1l = 0.0,
- aVSurf2f = 0.0, aVSurf2l = 0.0;
-
- theBW.UVS1().Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
- theBW.UVS2().Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
-
- Bnd_Range aRangeS1, aRangeS2;
- theBW.BoundaryEstimation(theCyl1, theCyl2, aRangeS1, aRangeS2);
- if (aRangeS1.IsVoid() || aRangeS2.IsVoid())
- return IntPatch_ImpImpIntersection::IntStatus_OK;
-
- {
- //Quotation of the message from issue #26894 (author MSV):
- //"We should return fail status from intersector if the result should be an
- //infinite curve of non-analytical type... I propose to define the limit for the
- //extent as the radius divided by 1e+2 and multiplied by 1e+7.
- //Thus, taking into account the number of valuable digits (15), we provide reliable
- //computations with an error not exceeding R/100."
- const Standard_Real aF = 1.0e+5;
- const Standard_Real aMaxV1Range = aF*theCyl1.Radius(), aMaxV2Range = aF*theCyl2.Radius();
- if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range))
- return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve;
- }
- //
- Standard_Boolean isGoodIntersection = Standard_False;
- Standard_Real anOptdu = 0.;
- for (;;)
- {
- //Checking parameters of cylinders in order to define "good intersection"
- //"Good intersection" means that axes of cylinders are almost perpendicular and
- // one radius is much smaller than the other and small cylinder is "inside" big one.
- const Standard_Real aToMuchCoeff = 3.;
- const Standard_Real aCritAngle = M_PI / 18.; // 10 degree
- Standard_Real anR1 = theCyl1.Radius();
- Standard_Real anR2 = theCyl2.Radius();
- Standard_Real anRmin = 0., anRmax = 0.;
- //Radius criterion
- if (anR1 > aToMuchCoeff * anR2)
- {
- anRmax = anR1; anRmin = anR2;
- }
- else if (anR2 > aToMuchCoeff * anR1)
- {
- anRmax = anR2; anRmin = anR1;
- }
- else
- {
- break;
- }
- //Angle criterion
- const gp_Ax1& anAx1 = theCyl1.Axis();
- const gp_Ax1& anAx2 = theCyl2.Axis();
- if (!anAx1.IsNormal(anAx2, aCritAngle))
- {
- break;
- }
- //Placement criterion
- gp_Lin anL1(anAx1), anL2(anAx2);
- Standard_Real aDist = anL1.Distance(anL2);
- if (aDist > anRmax / 2.)
- {
- break;
- }
-
- isGoodIntersection = Standard_True;
- //Estimation of "optimal" du
- //Relative deflection, absolut deflection is Rmin*aDeflection
- Standard_Real aDeflection = 0.001;
- Standard_Integer aNbP = 3;
- if (anRmin * aDeflection > 1.e-3)
- {
- Standard_Real anAngle = 1.0e0 - aDeflection;
- anAngle = 2.0e0 * ACos(anAngle);
- aNbP = (Standard_Integer)(2. * M_PI / anAngle) + 1;
- }
- anOptdu = 2. * M_PI_2 / (Standard_Real)(aNbP - 1);
- break;
- }
-//
- const ComputationMethods::stCoeffsValue &anEquationCoeffs = theBW.SICoeffs();
- const IntSurf_Quadric& aQuad1 = theBW.GetQSurface(1);
- const IntSurf_Quadric& aQuad2 = theBW.GetQSurface(2);
- const Standard_Boolean isReversed = theBW.IsReversed();
- const Standard_Real aTol2D = theBW.Get2dTolerance();
- const Standard_Real aTol3D = theBW.Get3dTolerance();
- const Standard_Real aPeriod = 2.0*M_PI;
- Standard_Integer aNbMaxPoints = 1000;
- Standard_Integer aNbMinPoints = 200;
- Standard_Real du;
- if (isGoodIntersection)
- {
- du = anOptdu;
- aNbMaxPoints = 200;
- aNbMinPoints = 50;
- }
- else
- {
- du = 2. * M_PI / aNbMaxPoints;
- }
- Standard_Integer aNbPts = Min(RealToInt((aUSurf1l - aUSurf1f) / du) + 1,
- RealToInt(20.0*theCyl1.Radius()));
- const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, aNbPts), aNbMaxPoints);
- const Standard_Real aStepMin = Max(aTol2D, Precision::PConfusion()),
- aStepMax = (aUSurf1l - aUSurf1f > M_PI / 100.0) ?
- (aUSurf1l - aUSurf1f) / IntToReal(aNbPoints) : aUSurf1l - aUSurf1f;
-
-
- //The main idea of the algorithm is to change U1-parameter
- //(U-parameter of theCyl1) from aU1f to aU1l with some step
- //(step is adaptive) and to obtain set of intersection points.
-
- for (Standard_Integer i = 0; i < theNbOfRanges; i++)
- {
- if (theRange[i].IsVoid())
- continue;
-
- InscribeInterval(aUSurf1f, aUSurf1l, theRange[i], aTol2D, aPeriod);
- }
-
- if (theRange[0].Union(theRange[1]))
- {
- // Works only if (theNbOfRanges == 2).
- theRange[1].SetVoid();
- }
-
- //Critical points are the value of U1-parameter in the points
- //where WL must be decomposed.
-
- //When U1 goes through critical points its value is set up to this
- //parameter forcefully and the intersection point is added in the line.
- //After that, the WL is broken (next U1 value will be correspond to the new WL).
-
- //See CriticalPointsComputing(...) function to get detail information about this array.
- const Standard_Integer aNbCritPointsMax = 12;
- Standard_Real anU1crit[aNbCritPointsMax] = { Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite(),
- Precision::Infinite() };
-
- //This list of critical points is not full because it does not contain any points
- //which intersection line goes through V-bounds of cylinders in.
- //They are computed by numerical methods on - line (during algorithm working).
- //The moment is caught, when intersection line goes through V-bounds of any cylinder.
-
- Standard_Integer aNbCritPoints = aNbCritPointsMax;
- CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aPeriod, aTol2D, aNbCritPoints, anU1crit);
-
- //Getting Walking-line
-
- enum WLFStatus
- {
- // No points have been added in WL
- WLFStatus_Absent = 0,
- // WL contains at least one point
- WLFStatus_Exist = 1,
- // WL has been finished in some critical point
- // We should start new line
- WLFStatus_Broken = 2
- };
-
- const Standard_Integer aNbWLines = 2;
- for (Standard_Integer aCurInterval = 0; aCurInterval < theNbOfRanges; aCurInterval++)
- {
- //Process every continuous region
- Standard_Boolean isAddedIntoWL[aNbWLines];
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- isAddedIntoWL[i] = Standard_False;
-
- Standard_Real anUf = 1.0, anUl = 0.0;
- if (!theRange[aCurInterval].GetBounds(anUf, anUl))
- continue;
-
- const Standard_Boolean isDeltaPeriod = IsEqual(anUl - anUf, aPeriod);
-
- //Inscribe and sort critical points
- for (Standard_Integer i = 0; i < aNbCritPoints; i++)
- {
- InscribePoint(anUf, anUl, anU1crit[i], 0.0, aPeriod, Standard_False);
- }
-
- std::sort(anU1crit, anU1crit + aNbCritPoints);
-
- while (anUf < anUl)
- {
- //Change value of U-parameter on the 1st surface from anUf to anUl
- //(anUf will be modified in the cycle body).
- //Step is computed adaptively (see comments below).
-
- Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
- WLFStatus aWLFindStatus[aNbWLines];
- Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
- Standard_Real anUexpect[aNbWLines];
- Standard_Boolean isAddingWLEnabled[aNbWLines];
-
- Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
- Handle(IntPatch_WLine) aWLine[aNbWLines];
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- aL2S[i] = new IntSurf_LineOn2S();
- aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
- aWLine[i]->SetCreatingWayInfo(IntPatch_WLine::IntPatch_WLImpImp);
- aWLFindStatus[i] = WLFStatus_Absent;
- isAddingWLEnabled[i] = Standard_True;
- aU2[i] = aV1[i] = aV2[i] = 0.0;
- aV1Prev[i] = aV2Prev[i] = 0.0;
- anUexpect[i] = anUf;
- }
-
- Standard_Real aCriticalDelta[aNbCritPointsMax] = { 0 };
- for (Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++)
- { //We are not interested in elements of aCriticalDelta array
- //if their index is greater than or equal to aNbCritPoints
-
- aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID];
- }
-
- Standard_Real anU1 = anUf, aMinCriticalParam = anUf;
- Standard_Boolean isFirst = Standard_True;
-
- while (anU1 <= anUl)
- {
- //Change value of U-parameter on the 1st surface from anUf to anUl
- //(anUf will be modified in the cycle body). However, this cycle
- //can be broken if WL goes though some critical point.
- //Step is computed adaptively (see comments below).
-
- for (Standard_Integer i = 0; i < aNbCritPoints; i++)
- {
- if ((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
- {
- //WL has gone through i-th critical point
- anU1 = anU1crit[i];
-
- for (Standard_Integer j = 0; j < aNbWLines; j++)
- {
- aWLFindStatus[j] = WLFStatus_Broken;
- anUexpect[j] = anU1;
- }
-
- break;
- }
- }
-
- if (IsEqual(anU1, anUl))
- {
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- aWLFindStatus[i] = WLFStatus_Broken;
- anUexpect[i] = anU1;
-
- if (isDeltaPeriod)
- {
- //if isAddedIntoWL[i] == TRUE WLine contains only one point
- //(which was end point of previous WLine). If we will
- //add point found on the current step WLine will contain only
- //two points. At that both these points will be equal to the
- //points found earlier. Therefore, new WLine will repeat
- //already existing WLine. Consequently, it is necessary
- //to forbid building new line in this case.
-
- isAddingWLEnabled[i] = (!isAddedIntoWL[i]);
- }
- else
- {
- isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) ||
- (aWLFindStatus[i] == WLFStatus_Absent));
- }
- }//for(Standard_Integer i = 0; i < aNbWLines; i++)
- }
- else
- {
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) ||
- (aWLFindStatus[i] == WLFStatus_Absent));
- }//for(Standard_Integer i = 0; i < aNbWLines; i++)
- }
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- const Standard_Integer aNbPntsWL = aWLine[i].IsNull() ? 0 :
- aWLine[i]->Curve()->NbPoints();
-
- if ((aWLFindStatus[i] == WLFStatus_Broken) ||
- (aWLFindStatus[i] == WLFStatus_Absent))
- {//Begin and end of WLine must be on boundary point
- //or on seam-edge strictly (if it is possible).
-
- Standard_Real aTol = aTol2D;
- ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs,
- aU2[i], &aTol);
- InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False);
-
- aTol = Max(aTol, aTol2D);
-
- if (Abs(aU2[i]) <= aTol)
- aU2[i] = 0.0;
- else if (Abs(aU2[i] - aPeriod) <= aTol)
- aU2[i] = aPeriod;
- else if (Abs(aU2[i] - aUSurf2f) <= aTol)
- aU2[i] = aUSurf2f;
- else if (Abs(aU2[i] - aUSurf2l) <= aTol)
- aU2[i] = aUSurf2l;
- }
- else
- {
- ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
- InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False);
- }
-
- if (aNbPntsWL == 0)
- {//the line has not contained any points yet
- if (((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*aTol2D) &&
- ((Abs(aU2[i] - aUSurf2f) < aTol2D) ||
- (Abs(aU2[i] - aUSurf2l) < aTol2D)))
- {
- //In this case aU2[i] can have two values: current aU2[i] or
- //aU2[i]+aPeriod (aU2[i]-aPeriod). It is necessary to choose
- //correct value.
-
- Standard_Boolean isIncreasing = Standard_True;
- ComputationMethods::CylCylMonotonicity(anU1+aStepMin, i, anEquationCoeffs,
- aPeriod, isIncreasing);
-
- //If U2(U1) is increasing and U2 is considered to be equal aUSurf2l
- //then after the next step (when U1 will be increased) U2 will be
- //increased too. And we will go out of surface boundary.
- //Therefore, If U2(U1) is increasing then U2 must be equal aUSurf2f.
- //Analogically, if U2(U1) is decreasing.
- if (isIncreasing)
- {
- aU2[i] = aUSurf2f;
- }
- else
- {
- aU2[i] = aUSurf2l;
- }
- }
- }
- else
- {//aNbPntsWL > 0
- if (((aUSurf2l - aUSurf2f) >= aPeriod) &&
- ((Abs(aU2[i] - aUSurf2f) < aTol2D) ||
- (Abs(aU2[i] - aUSurf2l) < aTol2D)))
- {//end of the line
- Standard_Real aU2prev = 0.0, aV2prev = 0.0;
- if (isReversed)
- aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev);
- else
- aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev);
-
- if (2.0*Abs(aU2prev - aU2[i]) > aPeriod)
- {
- if (aU2prev > aU2[i])
- aU2[i] += aPeriod;
- else
- aU2[i] -= aPeriod;
- }
- }
- }
-
- ComputationMethods::CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs,
- aV1[i], aV2[i]);
-
- if (isFirst)
- {
- aV1Prev[i] = aV1[i];
- aV2Prev[i] = aV2[i];
- }
- }//for(Standard_Integer i = 0; i < aNbWLines; i++)
-
- isFirst = Standard_False;
-
- //Looking for points into WLine
- Standard_Boolean isBroken = Standard_False;
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if (!isAddingWLEnabled[i])
- {
- Standard_Boolean isBoundIntersect = Standard_False;
- if ((Abs(aV1[i] - aVSurf1f) <= aTol2D) ||
- ((aV1[i] - aVSurf1f)*(aV1Prev[i] - aVSurf1f) < 0.0))
- {
- isBoundIntersect = Standard_True;
- }
- else if ((Abs(aV1[i] - aVSurf1l) <= aTol2D) ||
- ((aV1[i] - aVSurf1l)*(aV1Prev[i] - aVSurf1l) < 0.0))
- {
- isBoundIntersect = Standard_True;
- }
- else if ((Abs(aV2[i] - aVSurf2f) <= aTol2D) ||
- ((aV2[i] - aVSurf2f)*(aV2Prev[i] - aVSurf2f) < 0.0))
- {
- isBoundIntersect = Standard_True;
- }
- else if ((Abs(aV2[i] - aVSurf2l) <= aTol2D) ||
- ((aV2[i] - aVSurf2l)*(aV2Prev[i] - aVSurf2l) < 0.0))
- {
- isBoundIntersect = Standard_True;
- }
-
- if (aWLFindStatus[i] == WLFStatus_Broken)
- isBroken = Standard_True;
-
- if (!isBoundIntersect)
- {
- continue;
- }
- else
- {
- anUexpect[i] = anU1;
- }
- }
-
- // True if the current point already in the domain
- const Standard_Boolean isInscribe =
- ((aUSurf2f - aU2[i]) <= aTol2D) && ((aU2[i] - aUSurf2l) <= aTol2D) &&
- ((aVSurf1f - aV1[i]) <= aTol2D) && ((aV1[i] - aVSurf1l) <= aTol2D) &&
- ((aVSurf2f - aV2[i]) <= aTol2D) && ((aV2[i] - aVSurf2l) <= aTol2D);
-
- //isVIntersect == TRUE if intersection line intersects two (!)
- //V-bounds of cylinder (1st or 2nd - no matter)
- const Standard_Boolean isVIntersect =
- (((aVSurf1f - aV1[i])*(aVSurf1f - aV1Prev[i]) < RealSmall()) &&
- ((aVSurf1l - aV1[i])*(aVSurf1l - aV1Prev[i]) < RealSmall())) ||
- (((aVSurf2f - aV2[i])*(aVSurf2f - aV2Prev[i]) < RealSmall()) &&
- ((aVSurf2l - aV2[i])*(aVSurf2l - aV2Prev[i]) < RealSmall()));
-
- //isFound1 == TRUE if intersection line intersects V-bounds
- // (First or Last - no matter) of the 1st cylynder
- //isFound2 == TRUE if intersection line intersects V-bounds
- // (First or Last - no matter) of the 2nd cylynder
- Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
- Standard_Boolean isForce = Standard_False;
-
- if (aWLFindStatus[i] == WLFStatus_Absent)
- {
- if (((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1 - aUSurf1l) < aTol2D))
- {
- isForce = Standard_True;
- }
- }
-
- theBW.AddBoundaryPoint(aWLine[i], anU1, aMinCriticalParam, aU2[i],
- aV1[i], aV1Prev[i], aV2[i], aV2Prev[i], i, isForce,
- isFound1, isFound2);
-
- const Standard_Boolean isPrevVBound = !isVIntersect &&
- ((Abs(aV1Prev[i] - aVSurf1f) <= aTol2D) ||
- (Abs(aV1Prev[i] - aVSurf1l) <= aTol2D) ||
- (Abs(aV2Prev[i] - aVSurf2f) <= aTol2D) ||
- (Abs(aV2Prev[i] - aVSurf2l) <= aTol2D));
-
- aV1Prev[i] = aV1[i];
- aV2Prev[i] = aV2[i];
-
- if ((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound)
- {
- aWLFindStatus[i] = WLFStatus_Broken; //start a new line
- }
- else if (isInscribe)
- {
- if ((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2))
- {
- aWLFindStatus[i] = WLFStatus_Exist;
- }
-
- if ((aWLFindStatus[i] != WLFStatus_Broken) ||
- (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl))
- {
- if (aWLine[i]->NbPnts() > 0)
- {
- Standard_Real aU2p = 0.0, aV2p = 0.0;
- if (isReversed)
- aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
- else
- aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
-
- const Standard_Real aDelta = aU2[i] - aU2p;
-
- if (2.0 * Abs(aDelta) > aPeriod)
- {
- if (aDelta > 0.0)
- {
- aU2[i] -= aPeriod;
- }
- else
- {
- aU2[i] += aPeriod;
- }
- }
- }
-
- if(AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, Standard_True,
- gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]),
- aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod,
- aWLine[i]->Curve(), i, aTol3D, aTol2D, isForce))
- {
- if (aWLFindStatus[i] == WLFStatus_Absent)
- {
- aWLFindStatus[i] = WLFStatus_Exist;
- }
- }
- else if (!isFound1 && !isFound2)
- {//We do not add any point while doing this iteration
- if (aWLFindStatus[i] == WLFStatus_Exist)
- {
- aWLFindStatus[i] = WLFStatus_Broken;
- }
- }
- }
- }
- else
- {//We do not add any point while doing this iteration
- if (aWLFindStatus[i] == WLFStatus_Exist)
- {
- aWLFindStatus[i] = WLFStatus_Broken;
- }
- }
-
- if (aWLFindStatus[i] == WLFStatus_Broken)
- isBroken = Standard_True;
- }//for(Standard_Integer i = 0; i < aNbWLines; i++)
-
- if (isBroken)
- {//current lines are filled. Go to the next lines
- anUf = anU1;
-
- Standard_Boolean isAdded = Standard_True;
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if (isAddingWLEnabled[i])
- {
- continue;
- }
-
- isAdded = Standard_False;
-
- Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
-
- theBW.AddBoundaryPoint(aWLine[i], anU1, aMinCriticalParam, aU2[i],
- aV1[i], aV1Prev[i], aV2[i], aV2Prev[i], i,
- Standard_False, isFound1, isFound2);
-
- if (isFound1 || isFound2)
- {
- isAdded = Standard_True;
- }
-
- if (aWLine[i]->NbPnts() > 0)
- {
- Standard_Real aU2p = 0.0, aV2p = 0.0;
- if (isReversed)
- aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
- else
- aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
-
- const Standard_Real aDelta = aU2[i] - aU2p;
-
- if (2 * Abs(aDelta) > aPeriod)
- {
- if (aDelta > 0.0)
- {
- aU2[i] -= aPeriod;
- }
- else
- {
- aU2[i] += aPeriod;
- }
- }
- }
-
- if(AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed,
- Standard_True, gp_Pnt2d(anU1, aV1[i]),
- gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l,
- aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l,
- aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(),
- i, aTol3D, aTol2D, Standard_False))
- {
- isAdded = Standard_True;
- }
- }
-
- if (!isAdded)
- {
- //Before breaking WL, we must complete it correctly
- //(e.g. to prolong to the surface boundary).
- //Therefore, we take the point last added in some WL
- //(have maximal U1-parameter) and try to add it in
- //the current WL.
- Standard_Real anUmaxAdded = RealFirst();
-
- {
- Standard_Boolean isChanged = Standard_False;
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if ((aWLFindStatus[i] == WLFStatus_Absent) || (aWLine[i]->NbPnts() == 0))
- continue;
-
- Standard_Real aU1c = 0.0, aV1c = 0.0;
- if (isReversed)
- aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
- else
- aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
-
- anUmaxAdded = Max(anUmaxAdded, aU1c);
- isChanged = Standard_True;
- }
-
- if (!isChanged)
- { //If anUmaxAdded were not changed in previous cycle then
- //we would break existing WLines.
- break;
- }
- }
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if (isAddingWLEnabled[i])
- {
- continue;
- }
-
- ComputationMethods::CylCylComputeParameters(anUmaxAdded, i, anEquationCoeffs,
- aU2[i], aV1[i], aV2[i]);
-
- AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed,
- Standard_True, gp_Pnt2d(anUmaxAdded, aV1[i]),
- gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l,
- aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l,
- aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(),
- i, aTol3D, aTol2D, Standard_False);
- }
- }
-
- break;
- }
-
- //Step computing
-
- {
- //Step of aU1-parameter is computed adaptively. The algorithm
- //aims to provide given aDeltaV1 and aDeltaV2 values (if it is
- //possible because the intersection line can go along V-isoline)
- //in every iteration. It allows avoiding "flying" intersection
- //points too far each from other (see issue #24915).
-
- const Standard_Real aDeltaV1 = aRangeS1.Delta() / IntToReal(aNbPoints),
- aDeltaV2 = aRangeS2.Delta() / IntToReal(aNbPoints);
-
- math_Matrix aMatr(1, 3, 1, 5);
-
- Standard_Real aMinUexp = RealLast();
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if (aTol2D < (anUexpect[i] - anU1))
- {
- continue;
- }
-
- if (aWLFindStatus[i] == WLFStatus_Absent)
- {
- anUexpect[i] += aStepMax;
- aMinUexp = Min(aMinUexp, anUexpect[i]);
- continue;
- }
- //
- if (isGoodIntersection)
- {
- //Use constant step
- anUexpect[i] += aStepMax;
- aMinUexp = Min(aMinUexp, anUexpect[i]);
-
- continue;
- }
- //
-
- Standard_Real aStepTmp = aStepMax;
-
- const Standard_Real aSinU1 = sin(anU1),
- aCosU1 = cos(anU1),
- aSinU2 = sin(aU2[i]),
- aCosU2 = cos(aU2[i]);
-
- aMatr.SetCol(1, anEquationCoeffs.mVecC1);
- aMatr.SetCol(2, anEquationCoeffs.mVecC2);
- aMatr.SetCol(3, anEquationCoeffs.mVecA1*aSinU1 - anEquationCoeffs.mVecB1*aCosU1);
- aMatr.SetCol(4, anEquationCoeffs.mVecA2*aSinU2 - anEquationCoeffs.mVecB2*aCosU2);
- aMatr.SetCol(5, anEquationCoeffs.mVecA1*aCosU1 + anEquationCoeffs.mVecB1*aSinU1 +
- anEquationCoeffs.mVecA2*aCosU2 + anEquationCoeffs.mVecB2*aSinU2 +
- anEquationCoeffs.mVecD);
-
- //The main idea is in solving of linearized system (2)
- //(see description to ComputationMethods class) in order to find new U1-value
- //to provide new value V1 or V2, which differs from current one by aDeltaV1 or
- //aDeltaV2 respectively.
-
- //While linearizing, following Taylor formulas are used:
- // cos(x0+dx) = cos(x0) - sin(x0)*dx
- // sin(x0+dx) = sin(x0) + cos(x0)*dx
-
- //Consequently cos(U1), cos(U2), sin(U1) and sin(U2) in the system (2)
- //must be substituted by corresponding values.
-
- //ATTENTION!!!
- //The solution is approximate. More over, all requirements to the
- //linearization must be satisfied in order to obtain quality result.
-
- if (!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp))
- {
- //To avoid cycling-up
- anUexpect[i] += aStepMax;
- aMinUexp = Min(aMinUexp, anUexpect[i]);
-
- continue;
- }
-
- if (aStepTmp < aStepMin)
- aStepTmp = aStepMin;
-
- if (aStepTmp > aStepMax)
- aStepTmp = aStepMax;
-
- anUexpect[i] = anU1 + aStepTmp;
- aMinUexp = Min(aMinUexp, anUexpect[i]);
- }
-
- anU1 = aMinUexp;
- }
-
- if (Precision::PConfusion() >= (anUl - anU1))
- anU1 = anUl;
-
- anUf = anU1;
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if (aWLine[i]->NbPnts() != 1)
- isAddedIntoWL[i] = Standard_False;
-
- if (anU1 == anUl)
- {//strictly equal. Tolerance is considered above.
- anUexpect[i] = anUl;
- }
- }
- }
-
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- if ((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
- {
- isTheEmpty = Standard_False;
- Standard_Real u1, v1, u2, v2;
- aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
- IntPatch_Point aP;
- aP.SetParameter(u1);
- aP.SetParameters(u1, v1, u2, v2);
- aP.SetTolerance(aTol3D);
- aP.SetValue(aWLine[i]->Point(1).Value());
-
- //Check whether the added point exists.
- //It is enough to check the last point.
- if (theSPnt.IsEmpty() ||
- !theSPnt.Last().PntOn2S().IsSame(aP.PntOn2S(), Precision::Confusion()))
- {
- theSPnt.Append(aP);
- }
- }
- else if (aWLine[i]->NbPnts() > 1)
- {
- Standard_Boolean isGood = Standard_True;
-
- if (aWLine[i]->NbPnts() == 2)
- {
- const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1);
- const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2);
-
- if (aPf.IsSame(aPl, Precision::Confusion()))
- isGood = Standard_False;
- }
- else if (aWLine[i]->NbPnts() > 2)
- {
- // Sometimes points of the WLine are distributed
- // linearly and uniformly. However, such position
- // of the points does not always describe the real intersection
- // curve. I.e. real tangents at the ends of the intersection
- // curve can significantly deviate from this "line" direction.
- // Here we are processing this case by inserting additional points
- // to the beginning/end of the WLine to make it more precise.
- // See description to the issue #30082.
-
- const Standard_Real aSqTol3D = aTol3D*aTol3D;
- for (Standard_Integer j = 0; j < 2; j++)
- {
- // If j == 0 ==> add point at begin of WLine.
- // If j == 1 ==> add point at end of WLine.
-
- for (;;)
- {
- if (aWLine[i]->NbPnts() >= aNbMaxPoints)
- {
- break;
- }
-
- // Take 1st and 2nd point to compute the "line" direction.
- // For our convenience, we make 2nd point be the ends of the WLine
- // because it will be used for computation of the normals
- // to the surfaces.
- const Standard_Integer anIdx1 = j ? aWLine[i]->NbPnts() - 1 : 2;
- const Standard_Integer anIdx2 = j ? aWLine[i]->NbPnts() : 1;
-
- const gp_Pnt &aP1 = aWLine[i]->Point(anIdx1).Value();
- const gp_Pnt &aP2 = aWLine[i]->Point(anIdx2).Value();
-
- const gp_Vec aDir(aP1, aP2);
-
- if (aDir.SquareMagnitude() < aSqTol3D)
- {
- break;
- }
-
- // Compute tangent in first/last point of the WLine.
- // We do not take into account the flag "isReversed"
- // because strict direction of the tangent is not
- // important here (we are interested in the tangent
- // line itself and nothing to fear if its direction
- // is reversed).
- const gp_Vec aN1 = aQuad1.Normale(aP2);
- const gp_Vec aN2 = aQuad2.Normale(aP2);
- const gp_Vec aTg(aN1.Crossed(aN2));
-
- if (aTg.SquareMagnitude() < Precision::SquareConfusion())
- {
- // Tangent zone
- break;
- }
-
- // Check of the bending
- Standard_Real anAngle = aDir.Angle(aTg);
-
- if (anAngle > M_PI_2)
- anAngle -= M_PI;
-
- if (Abs(anAngle) > 0.25) // ~ 14deg.
- {
- const Standard_Integer aNbPntsPrev = aWLine[i]->NbPnts();
- SeekAdditionalPoints(aQuad1, aQuad2, aWLine[i]->Curve(),
- anEquationCoeffs, i, 3, anIdx1, anIdx2,
- aTol2D, aPeriod, isReversed);
-
- if (aWLine[i]->NbPnts() == aNbPntsPrev)
- {
- // No points have been added. ==> Exit from a loop.
- break;
- }
- }
- else
- {
- // Good result has been achieved. ==> Exit from a loop.
- break;
- }
- } // for (;;)
- }
- }
-
- if (isGood)
- {
- isTheEmpty = Standard_False;
- isAddedIntoWL[i] = Standard_True;
- SeekAdditionalPoints(aQuad1, aQuad2, aWLine[i]->Curve(),
- anEquationCoeffs, i, aNbPoints, 1,
- aWLine[i]->NbPnts(), aTol2D, aPeriod,
- isReversed);
-
- aWLine[i]->ComputeVertexParameters(aTol3D);
- theSlin.Append(aWLine[i]);
- }
- }
- else
- {
- isAddedIntoWL[i] = Standard_False;
- }
-
-#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
- aWLine[i]->Dump(0);
-#endif
- }
- }
- }
-
-
- //Delete the points in theSPnt, which
- //lie at least in one of the line in theSlin.
- for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
- {
- for (Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++)
- {
- Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::
- DownCast(theSlin.Value(aNbLin)));
-
- const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
- const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aWLine1->NbPnts());
-
- const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNbPnt).PntOn2S();
- if (aPntCur.IsSame(aPntFWL1, aTol3D) ||
- aPntCur.IsSame(aPntLWL1, aTol3D))
- {
- theSPnt.Remove(aNbPnt);
- aNbPnt--;
- break;
- }
- }
- }
-
- //Try to add new points in the neighborhood of existing point
- for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
- {
- // Standard algorithm (implemented above) could not find any
- // continuous curve in neighborhood of aPnt2S (e.g. because
- // this curve is too small; see tests\bugs\modalg_5\bug25292_35 and _36).
- // Here, we will try to find several new points nearer to aPnt2S.
-
- // The algorithm below tries to find two points in every
- // intervals [u1 - aStepMax, u1] and [u1, u1 + aStepMax]
- // and every new point will be in maximal distance from
- // u1. If these two points exist they will be joined
- // by the intersection curve.
-
- const IntPatch_Point& aPnt2S = theSPnt.Value(aNbPnt);
-
- Standard_Real u1, v1, u2, v2;
- aPnt2S.Parameters(u1, v1, u2, v2);
-
- Handle(IntSurf_LineOn2S) aL2S = new IntSurf_LineOn2S();
- Handle(IntPatch_WLine) aWLine = new IntPatch_WLine(aL2S, Standard_False);
- aWLine->SetCreatingWayInfo(IntPatch_WLine::IntPatch_WLImpImp);
-
- //Define the index of WLine, which lies the point aPnt2S in.
- Standard_Integer anIndex = 0;
-
- Standard_Real anUf = 0.0, anUl = 0.0, aCurU2 = 0.0;
- if (isReversed)
- {
- anUf = Max(u2 - aStepMax, aUSurf1f);
- anUl = Min(u2 + aStepMax, aUSurf1l);
- aCurU2 = u1;
- }
- else
- {
- anUf = Max(u1 - aStepMax, aUSurf1f);
- anUl = Min(u1 + aStepMax, aUSurf1l);
- aCurU2 = u2;
- }
-
- const Standard_Real anUinf = anUf, anUsup = anUl, anUmid = 0.5*(anUf + anUl);
-
- {
- //Find the value of anIndex variable.
- Standard_Real aDelta = RealLast();
- for (Standard_Integer i = 0; i < aNbWLines; i++)
- {
- Standard_Real anU2t = 0.0;
- if (!ComputationMethods::CylCylComputeParameters(anUmid, i, anEquationCoeffs, anU2t))
- continue;
-
- Standard_Real aDU2 = fmod(Abs(anU2t - aCurU2), aPeriod);
- aDU2 = Min(aDU2, Abs(aDU2 - aPeriod));
- if (aDU2 < aDelta)
- {
- aDelta = aDU2;
- anIndex = i;
- }
- }
- }
-
- // Bisection method is used in order to find every new point.
- // I.e. if we need to find intersection point in the interval [anUinf, anUmid]
- // we check the point anUC = 0.5*(anUinf+anUmid). If it is an intersection point
- // we try to find another point in the interval [anUinf, anUC] (because we find the point in
- // maximal distance from anUmid). If it is not then we try to find another point in the
- // interval [anUC, anUmid]. Next iterations will be made analogically.
- // When we find intersection point in the interval [anUmid, anUsup] we try to find
- // another point in the interval [anUC, anUsup] if anUC is intersection point and
- // in the interval [anUmid, anUC], otherwise.
-
- Standard_Real anAddedPar[2] = {isReversed ? u2 : u1, isReversed ? u2 : u1};
-
- for (Standard_Integer aParID = 0; aParID < 2; aParID++)
- {
- if (aParID == 0)
- {
- anUf = anUinf;
- anUl = anUmid;
- }
- else // if(aParID == 1)
- {
- anUf = anUmid;
- anUl = anUsup;
- }
-
- Standard_Real &aPar1 = (aParID == 0) ? anUf : anUl,
- &aPar2 = (aParID == 0) ? anUl : anUf;
-
- while (Abs(aPar2 - aPar1) > aStepMin)
- {
- Standard_Real anUC = 0.5*(anUf + anUl);
- Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
- Standard_Boolean isDone = ComputationMethods::
- CylCylComputeParameters(anUC, anIndex, anEquationCoeffs, aU2, aV1, aV2);
-
- if (isDone)
- {
- if (Abs(aV1 - aVSurf1f) <= aTol2D)
- aV1 = aVSurf1f;
-
- if (Abs(aV1 - aVSurf1l) <= aTol2D)
- aV1 = aVSurf1l;
-
- if (Abs(aV2 - aVSurf2f) <= aTol2D)
- aV2 = aVSurf2f;
-
- if (Abs(aV2 - aVSurf2l) <= aTol2D)
- aV2 = aVSurf2l;
-
- isDone = AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed,
- Standard_True, gp_Pnt2d(anUC, aV1), gp_Pnt2d(aU2, aV2),
- aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l,
- aPeriod, aWLine->Curve(), anIndex, aTol3D,
- aTol2D, Standard_False, Standard_True);
- }
-
- if (isDone)
- {
- anAddedPar[0] = Min(anAddedPar[0], anUC);
- anAddedPar[1] = Max(anAddedPar[1], anUC);
- aPar2 = anUC;
- }
- else
- {
- aPar1 = anUC;
- }
- }
- }
-
- //Fill aWLine by additional points
- if (anAddedPar[1] - anAddedPar[0] > aStepMin)
- {
- for (Standard_Integer aParID = 0; aParID < 2; aParID++)
- {
- Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
- ComputationMethods::CylCylComputeParameters(anAddedPar[aParID], anIndex,
- anEquationCoeffs, aU2, aV1, aV2);
-
- AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, Standard_True,
- gp_Pnt2d(anAddedPar[aParID], aV1), gp_Pnt2d(aU2, aV2),
- aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod, aWLine->Curve(),
- anIndex, aTol3D, aTol2D, Standard_False, Standard_False);
- }
-
- SeekAdditionalPoints(aQuad1, aQuad2, aWLine->Curve(),
- anEquationCoeffs, anIndex, aNbMinPoints,
- 1, aWLine->NbPnts(), aTol2D, aPeriod,
- isReversed);
-
- aWLine->ComputeVertexParameters(aTol3D);
- theSlin.Append(aWLine);
-
- theSPnt.Remove(aNbPnt);
- aNbPnt--;
- }
- }
-
- return IntPatch_ImpImpIntersection::IntStatus_OK;
-}
-
-//=======================================================================
-//function : IntCyCy
-//purpose :
-//=======================================================================
-IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTol3D,
- const Standard_Real theTol2D,
- const Bnd_Box2d& theUVSurf1,
- const Bnd_Box2d& theUVSurf2,
- Standard_Boolean& isTheEmpty,
- Standard_Boolean& isTheSameSurface,
- Standard_Boolean& isTheMultiplePoint,
- IntPatch_SequenceOfLine& theSlin,
- IntPatch_SequenceOfPoint& theSPnt)
-{
- isTheEmpty = Standard_True;
- isTheSameSurface = Standard_False;
- isTheMultiplePoint = Standard_False;
- theSlin.Clear();
- theSPnt.Clear();
-
- const gp_Cylinder aCyl1 = theQuad1.Cylinder(),
- aCyl2 = theQuad2.Cylinder();
-
- IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D);
-
- if (!anInter.IsDone())
- {
- return IntPatch_ImpImpIntersection::IntStatus_Fail;
- }
-
- if(anInter.TypeInter() != IntAna_NoGeometricSolution)
- {
- if (CyCyAnalyticalIntersect(theQuad1, theQuad2, anInter,
- theTol3D, isTheEmpty,
- isTheSameSurface, isTheMultiplePoint,
- theSlin, theSPnt))
- {
- return IntPatch_ImpImpIntersection::IntStatus_OK;
- }
- }
-
- //Here, intersection line is not an analytical curve(line, circle, ellipsis etc.)
-
- Standard_Real aUSBou[2][2], aVSBou[2][2]; //const
-
- theUVSurf1.Get(aUSBou[0][0], aVSBou[0][0], aUSBou[0][1], aVSBou[0][1]);
- theUVSurf2.Get(aUSBou[1][0], aVSBou[1][0], aUSBou[1][1], aVSBou[1][1]);
-
- const Standard_Real aPeriod = 2.0*M_PI;
- const Standard_Integer aNbWLines = 2;
-
- const ComputationMethods::stCoeffsValue anEquationCoeffs1(aCyl1, aCyl2);
- const ComputationMethods::stCoeffsValue anEquationCoeffs2(aCyl2, aCyl1);
-
- //Boundaries.
- //Intersection result can include two non-connected regions
- //(see WorkWithBoundaries::BoundariesComputing(...) method).
- const Standard_Integer aNbOfBoundaries = 2;
- Bnd_Range anURange[2][aNbOfBoundaries]; //const
-
- if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs1, aPeriod, anURange[0]))
- return IntPatch_ImpImpIntersection::IntStatus_OK;
-
- if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs2, aPeriod, anURange[1]))
- return IntPatch_ImpImpIntersection::IntStatus_OK;
-
- //anURange[*] can be in different periodic regions in
- //compare with First-Last surface. E.g. the surface
- //is full cylinder [0, 2*PI] but anURange is [5, 7].
- //Trivial common range computation returns [5, 2*PI] and
- //its summary length is 2*PI-5 == 1.28... only. That is wrong.
- //This problem can be solved by the following
- //algorithm:
- // 1. split anURange[*] by the surface boundary;
- // 2. shift every new range in order to inscribe it
- // in [Ufirst, Ulast] of cylinder;
- // 3. consider only common ranges between [Ufirst, Ulast]
- // and new ranges.
- //
- // In above example, we obtain following:
- // 1. two ranges: [5, 2*PI] and [2*PI, 7];
- // 2. after shifting: [5, 2*PI] and [0, 7-2*PI];
- // 3. Common ranges: ([5, 2*PI] and [0, 2*PI]) == [5, 2*PI],
- // ([0, 7-2*PI] and [0, 2*PI]) == [0, 7-2*PI];
- // 4. Their summary length is (2*PI-5)+(7-2*PI-0)==7-5==2 ==> GOOD.
-
- Standard_Real aSumRange[2] = { 0.0, 0.0 };
- Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
- for (Standard_Integer aCID = 0; aCID < 2; aCID++)
- {
- anAlloc->Reset(false);
- NCollection_List<Bnd_Range> aListOfRng(anAlloc);
-
- aListOfRng.Append(anURange[aCID][0]);
- aListOfRng.Append(anURange[aCID][1]);
-
- const Standard_Real aSplitArr[3] = {aUSBou[aCID][0], aUSBou[aCID][1], 0.0};
-
- NCollection_List<Bnd_Range>::Iterator anITrRng;
- for (Standard_Integer aSInd = 0; aSInd < 3; aSInd++)
- {
- NCollection_List<Bnd_Range> aLstTemp(aListOfRng);
- aListOfRng.Clear();
- for (anITrRng.Init(aLstTemp); anITrRng.More(); anITrRng.Next())
- {
- Bnd_Range& aRng = anITrRng.ChangeValue();
- aRng.Split(aSplitArr[aSInd], aListOfRng, aPeriod);
- }
- }
-
- anITrRng.Init(aListOfRng);
- for (; anITrRng.More(); anITrRng.Next())
- {
- Bnd_Range& aCurrRange = anITrRng.ChangeValue();
-
- Bnd_Range aBoundR;
- aBoundR.Add(aUSBou[aCID][0]);
- aBoundR.Add(aUSBou[aCID][1]);
-
- if (!InscribeInterval(aUSBou[aCID][0], aUSBou[aCID][1],
- aCurrRange, theTol2D, aPeriod))
- {
- //If aCurrRange does not have common block with
- //[Ufirst, Ulast] of cylinder then we will try
- //to inscribe [Ufirst, Ulast] in the boundaries of aCurrRange.
- Standard_Real aF = 1.0, aL = 0.0;
- if (!aCurrRange.GetBounds(aF, aL))
- continue;
-
- if ((aL < aUSBou[aCID][0]))
- {
- aCurrRange.Shift(aPeriod);
- }
- else if (aF > aUSBou[aCID][1])
- {
- aCurrRange.Shift(-aPeriod);
- }
- }
-
- aBoundR.Common(aCurrRange);
-
- const Standard_Real aDelta = aBoundR.Delta();
-
- if (aDelta > 0.0)
- {
- aSumRange[aCID] += aDelta;
- }
- }
- }
-
- //The bigger range the bigger number of points in Walking-line (WLine)
- //we will be able to add and consequently we will obtain more
- //precise intersection line.
- //Every point of WLine is determined as function from U1-parameter,
- //where U1 is U-parameter on 1st quadric.
- //Therefore, we should use quadric with bigger range as 1st parameter
- //in IntCyCy() function.
- //On the other hand, there is no point in reversing in case of
- //analytical intersection (when result is line, ellipse, point...).
- //This result is independent of the arguments order.
- const Standard_Boolean isToReverse = (aSumRange[1] > aSumRange[0]);
-
- if (isToReverse)
- {
- const WorkWithBoundaries aBoundWork(theQuad2, theQuad1, anEquationCoeffs2,
- theUVSurf2, theUVSurf1, aNbWLines,
- aPeriod, theTol3D, theTol2D, Standard_True);
-
- return CyCyNoGeometric(aCyl2, aCyl1, aBoundWork, anURange[1], aNbOfBoundaries,
- isTheEmpty, theSlin, theSPnt);
- }
- else
- {
- const WorkWithBoundaries aBoundWork(theQuad1, theQuad2, anEquationCoeffs1,
- theUVSurf1, theUVSurf2, aNbWLines,
- aPeriod, theTol3D, theTol2D, Standard_False);
-
- return CyCyNoGeometric(aCyl1, aCyl2, aBoundWork, anURange[0], aNbOfBoundaries,
- isTheEmpty, theSlin, theSPnt);
- }
-}
-
-//=======================================================================
-//function : IntCySp
-//purpose :
-//=======================================================================
-Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-{
- Standard_Integer i;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
- IntPatch_Point ptsol;
- gp_Circ cirsol;
-
- gp_Cylinder Cy;
- gp_Sphere Sp;
-
- if (!Reversed) {
- Cy = Quad1.Cylinder();
- Sp = Quad2.Sphere();
- }
- else {
- Cy = Quad2.Cylinder();
- Sp = Quad1.Sphere();
- }
- IntAna_QuadQuadGeo inter(Cy,Sp,Tol);
-
- if (!inter.IsDone()) {return Standard_False;}
-
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- Empty = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty :
- {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Point :
- {
- gp_Pnt psol(inter.Point(1));
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
-
- case IntAna_Circle:
- {
- cirsol = inter.Circle(1);
- gp_Vec Tgt;
- gp_Pnt ptref;
- ElCLib::D1(0.,cirsol,ptref,Tgt);
-
- if (NbSol == 1) {
- gp_Vec TestCurvature(ptref,Sp.Location());
- gp_Vec Normsp,Normcyl;
- if (!Reversed) {
- Normcyl = Quad1.Normale(ptref);
- Normsp = Quad2.Normale(ptref);
- }
- else {
- Normcyl = Quad2.Normale(ptref);
- Normsp = Quad1.Normale(ptref);
- }
-
- IntSurf_Situation situcyl;
- IntSurf_Situation situsp;
-
- if (Normcyl.Dot(TestCurvature) > 0.) {
- situsp = IntSurf_Outside;
- if (Normsp.Dot(Normcyl) > 0.) {
- situcyl = IntSurf_Inside;
- }
- else {
- situcyl = IntSurf_Outside;
- }
- }
- else {
- situsp = IntSurf_Inside;
- if (Normsp.Dot(Normcyl) > 0.) {
- situcyl = IntSurf_Outside;
- }
- else {
- situcyl = IntSurf_Inside;
- }
- }
- Handle(IntPatch_GLine) glig;
- if (!Reversed) {
- glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
- }
- else {
- glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
- }
- slin.Append(glig);
- }
- else {
- if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
-
- cirsol = inter.Circle(2);
- ElCLib::D1(0.,cirsol,ptref,Tgt);
- Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.0000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.0000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- }
- break;
-
- case IntAna_NoGeometricSolution:
- {
- gp_Pnt psol;
- Standard_Real U1,V1,U2,V2;
- IntAna_IntQuadQuad anaint(Cy,Sp,Tol);
- if (!anaint.IsDone()) {
- return Standard_False;
- }
-
- if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
- Empty = Standard_True;
- }
- else {
-
- NbSol = anaint.NbPnt();
- for (i = 1; i <= NbSol; i++) {
- psol = anaint.Point(i);
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
-
- gp_Pnt ptvalid,ptf,ptl;
- gp_Vec tgvalid;
- Standard_Real first,last,para;
- IntAna_Curve curvsol;
- Standard_Boolean tgfound;
- Standard_Integer kount;
-
- NbSol = anaint.NbCurve();
- for (i = 1; i <= NbSol; i++) {
- curvsol = anaint.Curve(i);
- curvsol.Domain(first,last);
- ptf = curvsol.Value(first);
- ptl = curvsol.Value(last);
-
- para = last;
- kount = 1;
- tgfound = Standard_False;
-
- while (!tgfound) {
- para = (1.123*first + para)/2.123;
- tgfound = curvsol.D1u(para,ptvalid,tgvalid);
- if (!tgfound) {
- kount ++;
- tgfound = kount > 5;
- }
- }
- Handle(IntPatch_ALine) alig;
- if (kount <= 5) {
- Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
- Quad1.Normale(ptvalid));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
- }
- else {
- alig = new IntPatch_ALine(curvsol,Standard_False);
- }
- Standard_Boolean TempFalse1a = Standard_False;
- Standard_Boolean TempFalse2a = Standard_False;
-
- //-- ptf et ptl : points debut et fin de alig
-
- ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1a,ptf,first,
- TempFalse2a,ptl,last,Multpoint,Tol);
- slin.Append(alig);
- } //-- boucle sur les lignes
- } //-- solution avec au moins une lihne
- }
- break;
-
- default:
- {
- return Standard_False;
- }
- }
- return Standard_True;
-}
-//=======================================================================
-//function : IntCyCo
-//purpose :
-//=======================================================================
-Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-{
- IntPatch_Point ptsol;
-
- Standard_Integer i;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
- gp_Circ cirsol;
-
- gp_Cylinder Cy;
- gp_Cone Co;
-
- if (!Reversed) {
- Cy = Quad1.Cylinder();
- Co = Quad2.Cone();
- }
- else {
- Cy = Quad2.Cylinder();
- Co = Quad1.Cone();
- }
- IntAna_QuadQuadGeo inter(Cy,Co,Tol);
-
- if (!inter.IsDone()) {return Standard_False;}
-
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- Empty = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty : {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Point :{
- gp_Pnt psol(inter.Point(1));
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad1.Parameters(psol,U2,V2);
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
-
- case IntAna_Circle: {
- gp_Vec Tgt;
- gp_Pnt ptref;
- Standard_Integer j;
- Standard_Real qwe;
- //
- for(j=1; j<=2; ++j) {
- cirsol = inter.Circle(j);
- ElCLib::D1(0.,cirsol,ptref,Tgt);
- qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- }
- break;
-
- case IntAna_NoGeometricSolution: {
- gp_Pnt psol;
- Standard_Real U1,V1,U2,V2;
- IntAna_IntQuadQuad anaint(Cy,Co,Tol);
- if (!anaint.IsDone()) {
- return Standard_False;
- }
-
- if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
- Empty = Standard_True;
- }
- else {
- NbSol = anaint.NbPnt();
- for (i = 1; i <= NbSol; i++) {
- psol = anaint.Point(i);
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
-
- gp_Pnt ptvalid, ptf, ptl;
- gp_Vec tgvalid;
- //
- Standard_Real first,last,para;
- Standard_Boolean tgfound,firstp,lastp,kept;
- Standard_Integer kount;
- //
- //
- //IntAna_Curve curvsol;
- IntAna_Curve aC;
- IntAna_ListOfCurve aLC;
- IntAna_ListIteratorOfListOfCurve aIt;
-
- //
- NbSol = anaint.NbCurve();
- for (i = 1; i <= NbSol; ++i) {
- kept = Standard_False;
- //curvsol = anaint.Curve(i);
- aC=anaint.Curve(i);
- aLC.Clear();
- ExploreCurve(Co, aC, 10.*Tol, aLC);
- //
- aIt.Initialize(aLC);
- for (; aIt.More(); aIt.Next()) {
- IntAna_Curve& curvsol=aIt.ChangeValue();
- //
- curvsol.Domain(first, last);
- firstp = !curvsol.IsFirstOpen();
- lastp = !curvsol.IsLastOpen();
- if (firstp) {
- ptf = curvsol.Value(first);
- }
- if (lastp) {
- ptl = curvsol.Value(last);
- }
- para = last;
- kount = 1;
- tgfound = Standard_False;
-
- while (!tgfound) {
- para = (1.123*first + para)/2.123;
- tgfound = curvsol.D1u(para,ptvalid,tgvalid);
- if (!tgfound) {
- kount ++;
- tgfound = kount > 5;
- }
- }
- Handle(IntPatch_ALine) alig;
- if (kount <= 5) {
- Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
- Quad1.Normale(ptvalid));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
- kept = Standard_True;
- }
- else {
- ptvalid = curvsol.Value(para);
- alig = new IntPatch_ALine(curvsol,Standard_False);
- kept = Standard_True;
- //-- std::cout << "Transition indeterminee" << std::endl;
- }
- if (kept) {
- Standard_Boolean Nfirstp = !firstp;
- Standard_Boolean Nlastp = !lastp;
- ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
- Nlastp,ptl,last,Multpoint,Tol);
- slin.Append(alig);
- }
- } // for (; aIt.More(); aIt.Next())
- } // for (i = 1; i <= NbSol; ++i)
- }
- }
- break;
-
- default:
- return Standard_False;
-
- } // switch (typint)
-
- return Standard_True;
-}
-//=======================================================================
-//function : ExploreCurve
-//purpose : Splits aC on several curves in the cone apex points.
-//=======================================================================
-Standard_Boolean ExploreCurve(const gp_Cone& theCo,
- IntAna_Curve& theCrv,
- const Standard_Real theTol,
- IntAna_ListOfCurve& theLC)
-{
- const Standard_Real aSqTol = theTol*theTol;
- const gp_Pnt aPapx(theCo.Apex());
-
- Standard_Real aT1, aT2;
- theCrv.Domain(aT1, aT2);
-
- theLC.Clear();
- //
- TColStd_ListOfReal aLParams;
- theCrv.FindParameter(aPapx, aLParams);
- if (aLParams.IsEmpty())
- {
- theLC.Append(theCrv);
- return Standard_False;
- }
-
- for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next())
- {
- Standard_Real aPrm = anItr.Value();
-
- if ((aPrm - aT1) < Precision::PConfusion())
- continue;
-
- Standard_Boolean isLast = Standard_False;
- if ((aT2 - aPrm) < Precision::PConfusion())
- {
- aPrm = aT2;
- isLast = Standard_True;
- }
-
- const gp_Pnt aP = theCrv.Value(aPrm);
- const Standard_Real aSqD = aP.SquareDistance(aPapx);
- if (aSqD < aSqTol)
- {
- IntAna_Curve aC1 = theCrv;
- aC1.SetDomain(aT1, aPrm);
- aT1 = aPrm;
- theLC.Append(aC1);
- }
-
- if (isLast)
- break;
- }
-
- if (theLC.IsEmpty())
- {
- theLC.Append(theCrv);
- return Standard_False;
- }
-
- if ((aT2 - aT1) > Precision::PConfusion())
- {
- IntAna_Curve aC1 = theCrv;
- aC1.SetDomain(aT1, aT2);
- theLC.Append(aC1);
- }
-
- return Standard_True;
-}
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <gce_MakeLin.hxx>
-
-//=======================================================================
-//function : IntCoCo
-//purpose :
-//=======================================================================
-Standard_Boolean IntCoCo(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- Standard_Boolean& Empty,
- Standard_Boolean& Same,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-{
- Standard_Integer i, NbSol;
- Standard_Real U1,V1,U2,V2;
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
- //
- gp_Cone Co1(Quad1.Cone());
- gp_Cone Co2(Quad2.Cone());
- //
- IntAna_QuadQuadGeo inter(Co1,Co2,Tol);
- if (!inter.IsDone()) {
- return Standard_False;
- }
- //
- typint = inter.TypeInter();
- NbSol = inter.NbSolutions();
- Empty = Standard_False;
- Same = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty :
- {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Same:
- {
- Same = Standard_True;
- }
- break;
-
- //modified by NIZNHY-PKV Wed Nov 30 12:56:06 2005f
- case IntAna_Line :{
- Standard_Real para, aDot;
- gp_Pnt aPApex1, aPApex2, ptbid;
- gp_Lin linsol;
- gp_Vec NormC1,NormC2;
- IntPatch_Point aPtsol;
- Handle(IntPatch_GLine) glig;
- //
- aPApex1=Co1.Apex();
- aPApex2=Co2.Apex();
- //
- if (NbSol==1) {
- IntSurf_Situation situC1, situC2;
- //
- linsol = inter.Line(1);
- para =ElCLib::Parameter(linsol, aPApex1);
- ptbid=ElCLib::Value(para+5., linsol);
- Quad1.Parameters(aPApex1, U1, V1);
- Quad2.Parameters(aPApex1, U2, V2);
- //
- aPtsol.SetValue(aPApex1, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- aPtsol.SetParameter(para);
- //
- NormC1=Quad1.Normale(ptbid);
- NormC2=Quad2.Normale(ptbid);
- aDot=NormC1.Dot(NormC2);
- if (aDot<0.) {
- situC1=IntSurf_Outside;
- situC2=IntSurf_Outside;
- }
- else {
- Standard_Real aR1, aR2;
- gp_Lin aLAx1(aPApex1, Co1.Axis().Direction());
- gp_Lin aLAx2(aPApex2, Co2.Axis().Direction());
- //
- aR1=aLAx1.Distance(ptbid);
- aR2=aLAx2.Distance(ptbid);
- //
- situC1=IntSurf_Inside;
- situC2=IntSurf_Outside;
- if (aR1>aR2) { // Intersection line parametrizes from Apex1 to Apex2,
- situC1=IntSurf_Outside; // So the distance between ptbid and aLAx1 is greater than the
- situC2=IntSurf_Inside; // distance between ptbid and aLAx2 and in that case Cone2
- // is inside Cone 1
- }
- }
- // 1
- glig=new IntPatch_GLine(linsol, Standard_True, situC1, situC2);
- glig->AddVertex(aPtsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- // 2
- linsol.SetDirection(linsol.Direction().Reversed());
- para =ElCLib::Parameter(linsol, aPApex1);
- aPtsol.SetParameter(para);
-
- glig = new IntPatch_GLine(linsol, Standard_True, situC2, situC1);
- glig->AddVertex(aPtsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- } // if (NbSol==1) {
- //////////////////////
- else if (NbSol==2) {
- //
- for (i=1; i<=2; ++i) {
- linsol = inter.Line(i);
- para =ElCLib::Parameter(linsol, aPApex1);
- ptbid=ElCLib::Value(para+5., linsol);
- Quad1.Parameters(aPApex1, U1, V1);
- Quad2.Parameters(aPApex1, U2, V2);
- //
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- if (linsol.Direction().
- DotCross(Quad2.Normale(ptbid),Quad1.Normale(ptbid)) >0.) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- //
- Multpoint = Standard_True;
- // 1,3
- aPtsol.SetValue(aPApex1, Tol, Standard_False);
- aPtsol.SetParameters(U1,V1,U2,V2);
- aPtsol.SetParameter(para);
- aPtsol.SetMultiple(Standard_True);
-
- glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
- glig->AddVertex(aPtsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- // 2,4
- linsol.SetDirection(linsol.Direction().Reversed());
- para = ElCLib::Parameter(linsol, aPApex1);
- aPtsol.SetParameter(para);
- glig = new IntPatch_GLine(linsol, Standard_False, trans1, trans2);
- glig->AddVertex(aPtsol);
- glig->SetFirstPoint(1);
- slin.Append(glig);
- //
- } //for (i=1; i<=2; ++i)
- } //else if (NbSol==2)
- }
- break;
- //modified by NIZNHY-PKV Wed Nov 30 12:56:10 2005t
-
- case IntAna_Point : {
- gp_Pnt ptcontact;
- gp_Pnt apex1(Co1.Apex());
- gp_Pnt apex2(Co2.Apex());
- Standard_Real param1,param2;
- Standard_Real paramapex1 = ElCLib::LineParameter(Co1.Axis(),apex1);
- Standard_Real paramapex2 = ElCLib::LineParameter(Co2.Axis(),apex2);
- for (i=1; i <= NbSol; i++) {
- ptcontact = inter.Point(i);
- param1 = ElCLib::LineParameter(Co1.Axis(),ptcontact);
- param2 = ElCLib::LineParameter(Co2.Axis(),ptcontact);
-
- Quad1.Parameters(ptcontact,U1,V1);
- Quad2.Parameters(ptcontact,U2,V2);
-
- if (apex1.Distance(ptcontact) <= Tol &&
- apex2.Distance(ptcontact) <= Tol) {
- IntPatch_Point ptsol;
- ptsol.SetValue(ptcontact,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- else if (param1 >= paramapex1 && param2 >= paramapex2) {
- IntPatch_Point ptsol;
- ptsol.SetValue(ptcontact,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- }
- }
- break;
-
- case IntAna_Circle:
- {
- IntPatch_Point aPtsol;
- gp_Vec Tgt;
- gp_Pnt ptref;
- for (i = 1; i <= NbSol; i++) {
- gp_Circ cirsol = inter.Circle(i);
- ElCLib::D1(0.,cirsol,ptref,Tgt);
- Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001){
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- if(inter.HasCommonGen()) {
- const gp_Pnt& aPChar = inter.PChar();
- Quad1.Parameters(aPChar, U1, V1);
- Quad2.Parameters(aPChar, U2, V2);
- aPtsol.SetValue(aPChar, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- aPtsol.SetParameter(0.);
- glig->AddVertex(aPtsol);
- }
- slin.Append(glig);
- }
- }
- break;
-
-
- case IntAna_Ellipse:
- {
- IntPatch_Point aPtsol;
- gp_Elips elipsol = inter.Ellipse(1);
-
- gp_Vec Tgt;
- gp_Pnt ptref;
- ElCLib::D1(0.,elipsol,ptref,Tgt);
-
- Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
- if(inter.HasCommonGen()) {
- const gp_Pnt& aPChar = inter.PChar();
- Quad1.Parameters(aPChar, U1, V1);
- Quad2.Parameters(aPChar, U2, V2);
- aPtsol.SetValue(aPChar, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- aPtsol.SetParameter(0.);
- glig->AddVertex(aPtsol);
- }
- slin.Append(glig);
-
- }
- break;
-
-
- case IntAna_Hyperbola:
- {
- IntPatch_Point aPtsol;
- gp_Vec Tgt;
- gp_Pnt ptref;
- for(i=1; i<=2; i++) {
- gp_Hypr hyprsol = inter.Hyperbola(i);
- ElCLib::D1(0.,hyprsol,ptref,Tgt);
- Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001){
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(hyprsol,Standard_False,trans1,trans2);
- if(inter.HasCommonGen()) {
- const gp_Pnt& aPChar = inter.PChar();
- Quad1.Parameters(aPChar, U1, V1);
- Quad2.Parameters(aPChar, U2, V2);
- aPtsol.SetValue(aPChar, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- aPtsol.SetParameter(0.);
- glig->AddVertex(aPtsol);
- }
- slin.Append(glig);
- }
- }
- break;
-
- case IntAna_Parabola:
- {
- IntPatch_Point aPtsol;
- gp_Parab parabsol = inter.Parabola(1);
-
- gp_Vec Tgtorig(parabsol.YAxis().Direction());
- Standard_Real ptran = Tgtorig.DotCross(Quad2.Normale(parabsol.Location()),
- Quad1.Normale(parabsol.Location()));
- if (ptran >0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (ptran <-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
-
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(parabsol,Standard_False,trans1,trans2);
- if(inter.HasCommonGen()) {
- const gp_Pnt& aPChar = inter.PChar();
- Quad1.Parameters(aPChar, U1, V1);
- Quad2.Parameters(aPChar, U2, V2);
- aPtsol.SetValue(aPChar, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- aPtsol.SetParameter(0.);
- glig->AddVertex(aPtsol);
- }
- slin.Append(glig);
- }
- break;
-
-
- case IntAna_NoGeometricSolution:
- {
- gp_Pnt psol;
- IntAna_IntQuadQuad anaint(Co1,Co2,Tol);
- if (!anaint.IsDone()) {
- return Standard_False;
- }
-
- if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
- Empty = Standard_True;
- }
- else {
- NbSol = anaint.NbPnt();
- for (i = 1; i <= NbSol; i++) {
- psol = anaint.Point(i);
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
-
- gp_Pnt ptvalid, ptf, ptl;
- gp_Vec tgvalid;
-
- Standard_Real first,last,para;
- Standard_Boolean tgfound,firstp,lastp,kept;
- Standard_Integer kount;
-
- NbSol = anaint.NbCurve();
- for (i = 1; i <= NbSol; i++) {
- Handle(IntPatch_ALine) alig;
- kept = Standard_False;
- IntAna_Curve curvsol = anaint.Curve(i);
- curvsol.Domain(first,last);
- firstp = !curvsol.IsFirstOpen();
- lastp = !curvsol.IsLastOpen();
- if (firstp) {
- ptf = curvsol.Value(first);
- }
- if (lastp) {
- ptl = curvsol.Value(last);
- }
- para = last;
- kount = 1;
- tgfound = Standard_False;
-
- while (!tgfound) {
- para = (1.123*first + para)/2.123;
- tgfound = curvsol.D1u(para,ptvalid,tgvalid);
- if(tgvalid.SquareMagnitude() < 1e-14) {
- //-- on se trouve ds un cas ou les normales n'auront pas de sens
- tgfound = Standard_False;
- }
-
- if (!tgfound) {
- kount ++;
- tgfound = kount > 5;
- }
- }
- if (kount <= 5) {
- Standard_Real qwe= tgvalid.DotCross(Quad2.Normale(ptvalid),
- Quad1.Normale(ptvalid));
- if(qwe > 0.000000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe < -0.000000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
- kept = Standard_True;
- }
- else {
- ptvalid = curvsol.Value(para);
- alig = new IntPatch_ALine(curvsol,Standard_False);
- kept = Standard_True;
- //-- cout << "Transition indeterminee" << endl;
- }
- if (kept) {
- Standard_Boolean Nfirstp = !firstp;
- Standard_Boolean Nlastp = !lastp;
- ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
- Nlastp,ptl,last,Multpoint,Tol);
- slin.Append(alig);
- }
- }
- }
- }
- break;
-
- default:
- {
- return Standard_False;
- }
- }
-
- //When two cones have common generatrix passing through apexes
- //it is necessary to add it is solution
- if(inter.HasCommonGen()) {
- Standard_Real para;
- IntPatch_Point aPtsol;
- gp_Pnt aPApex1, aPApex2;
- aPApex1=Co1.Apex();
- aPApex2=Co2.Apex();
- //common generatrix of cones
- gce_MakeLin aMkLin(aPApex1, aPApex2);
- const gp_Lin& linsol = aMkLin.Value();
- Handle(IntPatch_GLine) glig =
- new IntPatch_GLine(linsol,Standard_True,IntSurf_Undecided,IntSurf_Undecided);
-
- const gp_Pnt& aPChar = inter.PChar();
- Quad1.Parameters(aPChar, U1, V1);
- Quad2.Parameters(aPChar, U2, V2);
- aPtsol.SetValue(aPChar, Tol, Standard_False);
- aPtsol.SetParameters(U1, V1, U2, V2);
- para = ElCLib::Parameter(linsol, aPChar);
- aPtsol.SetParameter(para);
- glig->AddVertex(aPtsol);
-
- slin.Append(glig);
-
- }
-
- return Standard_True;
-}
-//=======================================================================
-//function : IntCoSp
-//purpose :
-//=======================================================================
-Standard_Boolean IntCoSp(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- const Standard_Boolean Reversed,
- Standard_Boolean& Empty,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-{
-
- Standard_Integer i;
-
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
-
- gp_Sphere Sp;
- gp_Cone Co;
- Standard_Real U1,V1,U2,V2;
-
- if (!Reversed) {
- Co = Quad1.Cone();
- Sp = Quad2.Sphere();
- }
- else {
- Co = Quad2.Cone();
- Sp = Quad1.Sphere();
- }
- IntAna_QuadQuadGeo inter(Sp,Co,Tol);
-
- if (!inter.IsDone()) {return Standard_False;}
-
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
- Empty = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty :
- {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Point :
- {
- gp_Pnt ptcontact;
- gp_Pnt apex(Co.Apex());
- Standard_Real param;
- Standard_Real paramapex = ElCLib::LineParameter(Co.Axis(),apex);
- for (i=1; i <= NbSol; i++) {
- ptcontact = inter.Point(i);
- param = ElCLib::LineParameter(Co.Axis(),ptcontact);
- Quad1.Parameters(ptcontact,U1,V1);
- Quad2.Parameters(ptcontact,U2,V2);
-
- if (apex.Distance(ptcontact) <= Tol) {
- IntPatch_Point ptsol;
- ptsol.SetValue(ptcontact,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- else if (param >= paramapex) {
- IntPatch_Point ptsol;
- ptsol.SetValue(ptcontact,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- }
- }
- break;
-
- case IntAna_Circle:
- {
- gp_Vec Tgt;
- gp_Pnt ptref;
-
- for (i=1; i<=NbSol; i++) {
- gp_Circ cirsol = inter.Circle(i);
- //-- param = ElCLib::LineParameter(Co.Axis(),
- //-- cirsol.Location());
- //-- if (param >= paramapex) {
-
- ElCLib::D1(0.,cirsol,ptref,Tgt);
- Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),
- Quad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe< -0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- //-- }
- }
- }
- break;
-
- case IntAna_PointAndCircle:
- {
- gp_Vec Tgt;
- gp_Pnt ptref;
- gp_Pnt apex(Co.Apex());
- Standard_Real param;
- Standard_Real paramapex = ElCLib::LineParameter(Co.Axis(),apex);
-
- // le point est necessairement l apex
- Quad1.Parameters(apex,U1,V1);
- Quad2.Parameters(apex,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(apex,Tol,Standard_False);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
-
- gp_Circ cirsol = inter.Circle(1);
- param = ElCLib::LineParameter(Co.Axis(),
- cirsol.Location());
- ElCLib::D1(0., cirsol, ptref, Tgt);
- Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),
- Quad1.Normale(ptref));
-
- if (param >= paramapex)
- {
- if (qwe > Precision::PConfusion())
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (qwe < -Precision::PConfusion())
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1 = trans2 = IntSurf_Undecided;
- }
- }
- else
- {
- if (qwe < -Precision::PConfusion())
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if (qwe > Precision::PConfusion())
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1 = trans2 = IntSurf_Undecided;
- }
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol, Standard_False, trans1, trans2);
- slin.Append(glig);
- }
- break;
-
- case IntAna_NoGeometricSolution:
- {
- gp_Pnt psol;
- IntAna_IntQuadQuad anaint(Co,Sp,Tol);
- if (!anaint.IsDone()) {
- return Standard_False;
- }
-
- if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
- Empty = Standard_True;
- }
- else {
- NbSol = anaint.NbPnt();
- for (i = 1; i <= NbSol; i++) {
- psol = anaint.Point(i);
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
-
- gp_Pnt ptvalid, ptf, ptl;
- gp_Vec tgvalid;
- Standard_Real first,last,para;
- Standard_Boolean tgfound,firstp,lastp,kept;
- Standard_Integer kount;
-
- NbSol = anaint.NbCurve();
- for (i = 1; i <= NbSol; i++) {
- Handle(IntPatch_ALine) alig;
- kept = Standard_False;
- IntAna_Curve curvsol = anaint.Curve(i);
- curvsol.Domain(first,last);
- firstp = !curvsol.IsFirstOpen();
- lastp = !curvsol.IsLastOpen();
- if (firstp) {
- ptf = curvsol.Value(first);
- }
- if (lastp) {
- ptl = curvsol.Value(last);
- }
- para = last;
- kount = 1;
- tgfound = Standard_False;
-
- while (!tgfound) {
- para = (1.123*first + para)/2.123;
- tgfound = curvsol.D1u(para,ptvalid,tgvalid);
- if (!tgfound) {
- kount ++;
- tgfound = kount > 5;
- }
- }
- if (kount <= 5) {
- para = ElCLib::LineParameter(Co.Axis(),ptvalid);
- Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
- Quad1.Normale(ptvalid));
- if(qwe> 0.000000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.000000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
- kept = Standard_True;
- }
- else {
- ptvalid = curvsol.Value(para);
- para = ElCLib::LineParameter(Co.Axis(),ptvalid);
- alig = new IntPatch_ALine(curvsol,Standard_False);
- kept = Standard_True;
- //-- cout << "Transition indeterminee" << endl;
- }
- if (kept) {
- Standard_Boolean Nfirstp = !firstp;
- Standard_Boolean Nlastp = !lastp;
- ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
- Nlastp,ptl,last,Multpoint,Tol);
- slin.Append(alig);
- }
- }
- }
- }
- break;
-
- default:
- {
- return Standard_False;
- }
- }
-
- return Standard_True;
-}
-//=======================================================================
-//function : IntSpSp
-//purpose :
-//=======================================================================
-Standard_Boolean IntSpSp(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- Standard_Boolean& Empty,
- Standard_Boolean& Same,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
-// Traitement du cas Sphere/Sphere
-
-{
- IntSurf_TypeTrans trans1,trans2;
- IntAna_ResultType typint;
- gp_Sphere sph1(Quad1.Sphere());
- gp_Sphere sph2(Quad2.Sphere());
-
- IntAna_QuadQuadGeo inter(sph1,sph2,Tol);
- if (!inter.IsDone()) {return Standard_False;}
-
- typint = inter.TypeInter();
- Empty = Standard_False;
- Same = Standard_False;
-
- switch (typint) {
-
- case IntAna_Empty :
- {
- Empty = Standard_True;
- }
- break;
-
- case IntAna_Same:
- {
- Same = Standard_True;
- }
- break;
-
- case IntAna_Point:
- {
- gp_Pnt psol(inter.Point(1));
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- IntPatch_Point ptsol;
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
- break;
-
- case IntAna_Circle:
- {
- gp_Circ cirsol = inter.Circle(1);
- gp_Pnt ptref;
- gp_Vec Tgt;
- ElCLib::D1(0.,cirsol,ptref,Tgt);
-
- Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
- if(qwe>0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
- slin.Append(glig);
- }
- break;
-
- default:
- {
- return Standard_False; // on ne doit pas passer ici
- }
- }
- return Standard_True;
-}
+++ /dev/null
-// Created on: 1992-05-07
-// Created by: Jacques GOUSSARD
-// Copyright (c) 1992-1999 Matra Datavision
-// Copyright (c) 1999-2012 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.
-
-
-static
- Standard_Boolean TreatResultTorus(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const IntAna_QuadQuadGeo& anInt,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin);
-
-//=======================================================================
-//function : IntCyTo
-//purpose :
-//=======================================================================
-Standard_Boolean IntCyTo(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTolTang,
- const Standard_Boolean bReversed,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- const gp_Cylinder aCyl = bReversed ? theQuad2.Cylinder() : theQuad1.Cylinder();
- const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
- //
- IntAna_QuadQuadGeo anInt(aCyl, aTorus, theTolTang);
- Standard_Boolean bRet =
- TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
- //
- return bRet;
-}
-
-//=======================================================================
-//function : IntCoTo
-//purpose :
-//=======================================================================
-Standard_Boolean IntCoTo(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTolTang,
- const Standard_Boolean bReversed,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- const gp_Cone aCone = bReversed ? theQuad2.Cone() : theQuad1.Cone();
- const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
- //
- IntAna_QuadQuadGeo anInt(aCone, aTorus, theTolTang);
- Standard_Boolean bRet =
- TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
- //
- return bRet;
-}
-
-//=======================================================================
-//function : IntSpTo
-//purpose :
-//=======================================================================
-Standard_Boolean IntSpTo(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTolTang,
- const Standard_Boolean bReversed,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- const gp_Sphere aSphere = bReversed ? theQuad2.Sphere() : theQuad1.Sphere();
- const gp_Torus aTorus = bReversed ? theQuad1.Torus() : theQuad2.Torus();
- //
- IntAna_QuadQuadGeo anInt(aSphere, aTorus, theTolTang);
- Standard_Boolean bRet =
- TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
- //
- return bRet;
-}
-
-//=======================================================================
-//function : IntToTo
-//purpose :
-//=======================================================================
-Standard_Boolean IntToTo(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Standard_Real theTolTang,
- Standard_Boolean& bSameSurf,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- const gp_Torus aTorus1 = theQuad1.Torus();
- const gp_Torus aTorus2 = theQuad2.Torus();
- //
- IntAna_QuadQuadGeo anInt(aTorus1, aTorus2, theTolTang);
- Standard_Boolean bRet = anInt.IsDone();
- if (bRet) {
- if (anInt.TypeInter() == IntAna_Same) {
- bEmpty = Standard_False;
- bSameSurf = Standard_True;
- } else {
- bRet = TreatResultTorus(theQuad1, theQuad2, anInt, bEmpty, theSeqLin);
- }
- }
- //
- return bRet;
-}
-
-//=======================================================================
-//function : TreatResultTorus
-//purpose :
-//=======================================================================
-static Standard_Boolean TreatResultTorus(const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const IntAna_QuadQuadGeo& anInt,
- Standard_Boolean& bEmpty,
- IntPatch_SequenceOfLine& theSeqLin)
-{
- Standard_Boolean bRet = anInt.IsDone();
- //
- if (!bRet) {
- return bRet;
- }
- //
- IntAna_ResultType typint = anInt.TypeInter();
- Standard_Integer NbSol = anInt.NbSolutions();
- bEmpty = Standard_False;
- //
- switch (typint) {
- case IntAna_Empty :
- bEmpty = Standard_True;
- break;
- //
- case IntAna_Circle : {
- Standard_Integer i;
- IntSurf_TypeTrans trans1, trans2;
- gp_Vec Tgt;
- gp_Pnt ptref;
- //
- for (i = 1; i <= NbSol; ++i) {
- gp_Circ aC = anInt.Circle(i);
- if (theQuad1.TypeQuadric() == theQuad2.TypeQuadric()) {
- AdjustToSeam(theQuad1.Torus(), aC);
- }
- ElCLib::D1(0., aC, ptref, Tgt);
- Standard_Real qwe = Tgt.DotCross(theQuad2.Normale(ptref),
- theQuad1.Normale(ptref));
- if(qwe> 0.00000001) {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe< -0.00000001) {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else {
- trans1=trans2=IntSurf_Undecided;
- }
- //
- Handle(IntPatch_GLine) glig =
- new IntPatch_GLine(aC, Standard_False, trans1, trans2);
- theSeqLin.Append(glig);
- }
- }
- break;
- //
- case IntAna_NoGeometricSolution:
- default:
- bRet = Standard_False;
- break;
- }
- //
- return bRet;
-}
IntWalk_IWalking.gxx
IntWalk_IWalking.lxx
-IntWalk_IWalking_1.gxx
-IntWalk_IWalking_2.gxx
-IntWalk_IWalking_3.gxx
-IntWalk_IWalking_4.gxx
-IntWalk_IWalking_5.gxx
-IntWalk_IWalking_6.gxx
IntWalk_IWLine.gxx
IntWalk_IWLine.lxx
IntWalk_PWalking.cxx
// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
+// Copyright (c) 1999-2024 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
+#include <Bnd_Range.hxx>
#include <IntWalk_StatusDeflection.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <NCollection_LocalArray.hxx>
+#include <Precision.hxx>
#include <Standard_ConstructionError.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TColgp_Array1OfPnt.hxx>
#include <math_FunctionSetRoot.hxx>
-#include <TColgp_Array1OfPnt.hxx>
+//-- IntWalk_IWalking_1.gxx
+
+#ifdef CHRONO
+ #include <OSD_Chronometer.hxx>
+OSD_Chronometer Chronrsnld;
+#endif
+
+//==================================================================================
+// function : IsTangentExtCheck
+// purpose : Additional check if the point (theU, theV) in parametric surface
+// is a tangent point.
+// If that is TRUE then we can go along any (!) direction in order to
+// obtain next intersection point. At present, this case is difficult
+// for processing. Therefore, we will return an empty intersection line
+// in this case.
+//==================================================================================
+static Standard_Boolean IsTangentExtCheck(TheIWFunction& theFunc,
+ const Standard_Real theU,
+ const Standard_Real theV,
+ const Standard_Real theStepU,
+ const Standard_Real theStepV,
+ const Standard_Real theUinf,
+ const Standard_Real theUsup,
+ const Standard_Real theVinf,
+ const Standard_Real theVsup)
+{
+ const Standard_Real aTol = theFunc.Tolerance();
+ const Standard_Integer aNbItems = 4;
+ const Standard_Real aParU[aNbItems] = {Min(theU + theStepU, theUsup), Max(theU - theStepU, theUinf), theU, theU};
+ const Standard_Real aParV[aNbItems] = {theV, theV, Min(theV + theStepV, theVsup), Max(theV - theStepV, theVinf)};
+
+ math_Vector aX(1, 2), aVal(1, 1);
+
+ for (Standard_Integer i = 0; i < aNbItems; i++)
+ {
+ aX.Value(1) = aParU[i];
+ aX.Value(2) = aParV[i];
+
+ if (!theFunc.Value(aX, aVal))
+ continue;
+
+ if (Abs(theFunc.Root()) > aTol)
+ return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+IntWalk_IWalking::IntWalk_IWalking(const Standard_Real Epsilon,
+ const Standard_Real Deflection,
+ const Standard_Real Increment,
+ const Standard_Boolean theToFillHoles)
+: done(Standard_False),
+ fleche(Deflection),
+ pas(Increment),
+ tolerance(1, 2),
+ epsilon(Epsilon * Epsilon),
+ reversed(Standard_False),
+ wd1(IntWalk_VectorOfWalkingData::allocator_type(new NCollection_IncAllocator)),
+ wd2(wd1.get_allocator()),
+ nbMultiplicities(wd1.get_allocator()),
+ Um(0.0),
+ UM(0.0),
+ Vm(0.0),
+ VM(0.0),
+ ToFillHoles(theToFillHoles)
+{}
+
+//=======================================================================
+//function : Reset
+//purpose : Clears NCollection_Vector-based containers and adds
+// dummy data to maintain start index of 1 and consistent with
+// previous TCollection_Sequence-based implementation and other
+// used TCollection-based containers
+//=======================================================================
+
+void IntWalk_IWalking::Clear()
+{
+ wd1.clear();
+ wd2.clear();
+ IntWalk_WalkingData aDummy;
+ aDummy.etat = -10;
+ aDummy.ustart = aDummy.vstart = 0.;
+ wd1.push_back(aDummy);
+ wd2.push_back(aDummy);
+ nbMultiplicities.clear();
+ nbMultiplicities.push_back(-1);
+
+ done = Standard_False;
+ seqAjout.Clear();
+ lines.Clear();
+}
+
+// ***************************************************************************
+// etat1=12 not tangent, not passes
+// etat1=11 tangent, not passes
+// etat1=2 not tangent, passes
+// etat1=1 tangent, passes
+// after a point is processed its state becomes negative.
+// ***************************************************************************
+// etat2=13 interior start point on closed line
+// etat2=12 interior start point on open line
+// (line initially closed -> la line s is open)
+// after a point is processed (or if it is passed over during
+// routing) its state becomes negative.
+// ****************************************************************************
+
+//
+// Perform with interior points
+//
+void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
+ const ThePOLIterator& Pnts2,
+ TheIWFunction& Func,
+ const ThePSurface& Caro,
+ const Standard_Boolean Reversed)
+
+{
+ Standard_Integer I;
+ Standard_Boolean Rajout = Standard_False;
+ Standard_Integer nbPnts1 = Pnts1.Length();
+ Standard_Integer nbPnts2 = Pnts2.Length();
+ Standard_Real U, V;
+
+ Clear();
+ reversed = Reversed;
+
+ Um = ThePSurfaceTool::FirstUParameter(Caro);
+ Vm = ThePSurfaceTool::FirstVParameter(Caro);
+ UM = ThePSurfaceTool::LastUParameter(Caro);
+ VM = ThePSurfaceTool::LastVParameter(Caro);
+
+ if (UM < Um)
+ {
+ Standard_Real utemp = UM;
+ UM = Um;
+ Um = utemp;
+ }
+ if (VM < Vm)
+ {
+ Standard_Real vtemp = VM;
+ VM = Vm;
+ Vm = vtemp;
+ }
+
+ const Standard_Real aStepU = pas * (UM - Um), aStepV = pas * (VM - Vm);
+
+ // Loading of etat1 and etat2 as well as ustart and vstart.
+
+ TColStd_SequenceOfReal Umult;
+ TColStd_SequenceOfReal Vmult;
+
+ Standard_Integer decal = 0;
+ wd1.reserve(nbPnts1 + decal);
+ nbMultiplicities.reserve(nbPnts1 + decal);
+ for (I = 1; I <= nbPnts1 + decal; I++)
+ {
+ const ThePointOfPath& PathPnt = Pnts1.Value(I - decal);
+ IntWalk_WalkingData aWD1;
+ aWD1.etat = 1;
+ if (!ThePointOfPathTool::IsPassingPnt(PathPnt))
+ aWD1.etat = 11;
+ if (!ThePointOfPathTool::IsTangent(PathPnt))
+ ++aWD1.etat;
+
+ if (aWD1.etat == 2)
+ {
+ aWD1.etat = 11;
+ }
+
+ ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
+ mySRangeU.Add(aWD1.ustart);
+ mySRangeV.Add(aWD1.vstart);
+
+ wd1.push_back(aWD1);
+ Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
+ nbMultiplicities.push_back(aNbMult);
+
+ for (Standard_Integer J = 1; J <= aNbMult; J++)
+ {
+ ThePointOfPathTool::Parameters(PathPnt, J, U, V);
+ Umult.Append(U);
+ Vmult.Append(V);
+ }
+ }
+
+ wd2.reserve(nbPnts2);
+ for (I = 1; I <= nbPnts2; I++)
+ {
+ IntWalk_WalkingData aWD2;
+ aWD2.etat = 1;
+ const IntSurf_InteriorPoint& anIP = Pnts2.Value(I);
+ ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
+ mySRangeU.Add(aWD2.ustart);
+ mySRangeV.Add(aWD2.vstart);
+
+ if (!IsTangentExtCheck(Func, aWD2.ustart, aWD2.vstart, aStepU, aStepV, Um, UM, Vm, VM))
+ aWD2.etat = 13;
+
+ wd2.push_back(aWD2);
+ }
+
+ tolerance(1) = ThePSurfaceTool::UResolution(Caro, Precision::Confusion());
+ tolerance(2) = ThePSurfaceTool::VResolution(Caro, Precision::Confusion());
+
+ Func.Set(Caro);
+
+ if (mySRangeU.Delta() > Max(tolerance(1), Precision::PConfusion()))
+ {
+ mySRangeU.Enlarge(mySRangeU.Delta());
+ mySRangeU.Common(Bnd_Range(Um, UM));
+ }
+ else
+ {
+ mySRangeU = Bnd_Range(Um, UM);
+ }
+
+ if (mySRangeV.Delta() > Max(tolerance(2), Precision::PConfusion()))
+ {
+ mySRangeV.Enlarge(mySRangeV.Delta());
+ mySRangeV.Common(Bnd_Range(Vm, VM));
+ }
+ else
+ {
+ mySRangeV = Bnd_Range(Vm, VM);
+ }
+
+ // calculation of all open lines
+ if (nbPnts1 != 0)
+ ComputeOpenLine(Umult, Vmult, Pnts1, Func, Rajout);
+
+ // calculation of all closed lines
+ if (nbPnts2 != 0)
+ ComputeCloseLine(Umult, Vmult, Pnts1, Pnts2, Func, Rajout);
+
+ if (ToFillHoles)
+ {
+ Standard_Integer MaxNbIter = 10, nb_iter = 0;
+ while (seqAlone.Length() > 1 && nb_iter < MaxNbIter)
+ {
+ nb_iter++;
+ IntSurf_SequenceOfInteriorPoint PntsInHoles;
+ TColStd_SequenceOfInteger CopySeqAlone = seqAlone;
+ FillPntsInHoles(Func, CopySeqAlone, PntsInHoles);
+ wd2.clear();
+ IntWalk_WalkingData aDummy;
+ aDummy.etat = -10;
+ aDummy.ustart = aDummy.vstart = 0.;
+ wd2.push_back(aDummy);
+ Standard_Integer nbHoles = PntsInHoles.Length();
+ wd2.reserve(nbHoles);
+ for (I = 1; I <= nbHoles; I++)
+ {
+ IntWalk_WalkingData aWD2;
+ aWD2.etat = 13;
+ const IntSurf_InteriorPoint& anIP = PntsInHoles.Value(I);
+ ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
+ wd2.push_back(aWD2);
+ }
+ ComputeCloseLine(Umult, Vmult, Pnts1, PntsInHoles, Func, Rajout);
+ }
+ }
+
+ for (I = 1; I <= nbPnts1; I++)
+ {
+ if (wd1[I].etat > 0)
+ seqSingle.Append(Pnts1(I));
+ }
+ done = Standard_True;
+}
+
+//
+// Perform without interior point
+//
+
+void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
+ TheIWFunction& Func,
+ const ThePSurface& Caro,
+ const Standard_Boolean Reversed)
+
+{
+ Standard_Integer I;
+ Standard_Boolean Rajout = Standard_False;
+ Standard_Integer nbPnts1 = Pnts1.Length();
+ Standard_Real U, V;
+
+ reversed = Reversed;
+
+ // Loading of etat1 as well as ustart1 and vstart1.
+
+ TColStd_SequenceOfReal Umult;
+ TColStd_SequenceOfReal Vmult;
+
+ wd1.reserve(nbPnts1);
+ for (I = 1; I <= nbPnts1; I++)
+ {
+ const ThePointOfPath& PathPnt = Pnts1.Value(I);
+ IntWalk_WalkingData aWD1;
+ aWD1.etat = 1;
+ if (!ThePointOfPathTool::IsPassingPnt(PathPnt))
+ aWD1.etat = 11;
+ if (!ThePointOfPathTool::IsTangent(PathPnt))
+ ++aWD1.etat;
+ ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
+ wd1.push_back(aWD1);
+ Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
+ nbMultiplicities.push_back(aNbMult);
+
+ for (Standard_Integer J = 1; J <= aNbMult; J++)
+ {
+ ThePointOfPathTool::Parameters(PathPnt, J, U, V);
+ Umult.Append(U);
+ Vmult.Append(V);
+ }
+ }
+
+ tolerance(1) = ThePSurfaceTool::UResolution(Caro, Precision::Confusion());
+ tolerance(2) = ThePSurfaceTool::VResolution(Caro, Precision::Confusion());
+
+ Um = ThePSurfaceTool::FirstUParameter(Caro);
+ Vm = ThePSurfaceTool::FirstVParameter(Caro);
+ UM = ThePSurfaceTool::LastUParameter(Caro);
+ VM = ThePSurfaceTool::LastVParameter(Caro);
+
+ if (UM < Um)
+ {
+ Standard_Real utemp = UM;
+ UM = Um;
+ Um = utemp;
+ }
+ if (VM < Vm)
+ {
+ Standard_Real vtemp = VM;
+ VM = Vm;
+ Vm = vtemp;
+ }
+
+ Func.Set(Caro);
+
+ // calcul de toutes les lignes ouvertes
+ if (nbPnts1 != 0)
+ ComputeOpenLine(Umult, Vmult, Pnts1, Func, Rajout);
+
+ for (I = 1; I <= nbPnts1; I++)
+ {
+ if (wd1[I].etat > 0)
+ seqSingle.Append(Pnts1(I));
+ }
+ done = Standard_True;
+}
+
+//-- IntWalk_IWalking_2.gxx
+
+#ifndef OCCT_DEBUG
+ #define No_Standard_RangeError
+ #define No_Standard_OutOfRange
+#endif
+
+static void CutVectorByTolerances(gp_Vec2d& theVector, const math_Vector& theTolerance)
+{
+ if (Abs(theVector.X()) < theTolerance(1))
+ theVector.SetX(0.);
+ if (Abs(theVector.Y()) < theTolerance(2))
+ theVector.SetY(0.);
+}
+
+// _______________________________________________
+//
+// Location of point (u, v) in the natural domain of a surface AND update
+// of couple (u, v) for the calculation of the next point.
+//
+Standard_Boolean IntWalk_IWalking::Cadrage(math_Vector& BornInf,
+ math_Vector& BornSup,
+ math_Vector& UVap,
+ Standard_Real& Step,
+ // Standard_Real& StepV,
+ const Standard_Integer StepSign) const
+
+// there are always :
+// BorInf(1) <= UVap(1) <= BornSup(1) et BorInf(2) <= UVap(2) <= BornSup(2)
+// 1) check if the process point is out of the natural domain of the surface.
+// 2) if yes the approximated point is located on border taking the best direction
+// the step and a limit blocating one of the parameters during the recent call of
+// FunctionSetRoot are modified;
+// 3) couple (u, v) is recomputed by approximation for the calculation of the next point.
+// 4) return Standard_True if location, Standard_False if no location.
+{
+ Standard_Real Duvx = previousd2d.X();
+ Standard_Real Duvy = previousd2d.Y();
+
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(UVap(1), UVap(2));
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(UVap(1), UVap(2));
+ }
+
+ Standard_Real U1 = UVap(1) + Step * Duvx * StepSign;
+ Standard_Real V1 = UVap(2) + Step * Duvy * StepSign;
+
+ Standard_Boolean infu = (U1 <= BornInf(1) + Precision::PConfusion());
+ Standard_Boolean supu = (U1 >= BornSup(1) - Precision::PConfusion());
+ Standard_Boolean infv = (V1 <= BornInf(2) + Precision::PConfusion());
+ Standard_Boolean supv = (V1 >= BornSup(2) - Precision::PConfusion());
+
+ Standard_Real theStepU, theStepV;
+
+ if (!infu && !supu && !infv && !supv)
+ {
+ UVap(1) = U1;
+ UVap(2) = V1;
+ return Standard_False;
+ }
+
+ if ((infu || supu) && (infv || supv))
+ {
+ if (infu)
+ { // jag 940616
+ if (Duvx)
+ {
+ theStepU = Abs((BornInf(1) - UVap(1)) / Duvx); // iso U =BornInf(1)
+ }
+ else
+ {
+ theStepU = Step;
+ }
+ }
+ else
+ {
+ if (Duvx)
+ {
+ theStepU = Abs((BornSup(1) - UVap(1)) / Duvx); // iso U =BornSup(1)
+ }
+ else
+ {
+ theStepU = Step;
+ }
+ }
+ if (infv)
+ { // jag 940616
+ if (Duvy)
+ {
+ theStepV = Abs((BornInf(2) - UVap(2)) / Duvy); // iso V =BornInf(2)
+ }
+ else
+ {
+ theStepV = Step;
+ }
+ }
+ else
+ {
+ if (Duvy)
+ {
+ theStepV = Abs((BornSup(2) - UVap(2)) / Duvy); // iso V =BornSup(2)
+ }
+ else
+ {
+ theStepV = Step;
+ }
+ }
+
+ if (theStepU <= theStepV)
+ {
+ Step = theStepU;
+ if (infu)
+ {
+ UVap(1) = BornInf(1);
+ BornSup(1) = BornInf(1);
+ }
+ else
+ {
+ UVap(1) = BornSup(1);
+ BornInf(1) = BornSup(1);
+ }
+ UVap(2) += Step * Duvy * StepSign;
+ }
+ else
+ {
+ Step = theStepV;
+ if (infv)
+ {
+ UVap(2) = BornInf(2);
+ BornSup(2) = BornInf(2);
+ }
+ else
+ {
+ UVap(2) = BornSup(2);
+ BornInf(2) = BornSup(2);
+ }
+ UVap(1) += Step * Duvx * StepSign;
+ }
+ return Standard_True;
+ }
+
+ else if (infu)
+ { // jag 940616
+ if (Duvx)
+ {
+ Standard_Real aStep = Abs((BornInf(1) - UVap(1)) / Duvx); // iso U =BornInf(1)
+ if (aStep < Step)
+ Step = aStep;
+ }
+ BornSup(1) = BornInf(1); // limit the parameter
+ UVap(1) = BornInf(1);
+ UVap(2) += Step * Duvy * StepSign;
+ return Standard_True;
+ }
+ else if (supu)
+ { // jag 940616
+ if (Duvx)
+ {
+ Standard_Real aStep = Abs((BornSup(1) - UVap(1)) / Duvx); // iso U =BornSup(1)
+ if (aStep < Step)
+ Step = aStep;
+ }
+ BornInf(1) = BornSup(1); // limit the parameter
+ UVap(1) = BornSup(1);
+ UVap(2) += Step * Duvy * StepSign;
+ return Standard_True;
+ }
+ else if (infv)
+ { // jag 940616
+ if (Duvy)
+ {
+ Standard_Real aStep = Abs((BornInf(2) - UVap(2)) / Duvy); // iso V =BornInf(2)
+ if (aStep < Step)
+ Step = aStep;
+ }
+ BornSup(2) = BornInf(2);
+ UVap(1) += Step * Duvx * StepSign;
+ UVap(2) = BornInf(2);
+ return Standard_True;
+ }
+ else if (supv)
+ { // jag 940616
+ if (Duvy)
+ {
+ Standard_Real aStep = Abs((BornSup(2) - UVap(2)) / Duvy); // iso V =BornSup(2)
+ if (aStep < Step)
+ Step = aStep;
+ }
+ BornInf(2) = BornSup(2);
+ UVap(1) += Step * Duvx * StepSign;
+ UVap(2) = BornSup(2);
+ return Standard_True;
+ }
+ return Standard_True;
+}
+
+Standard_Boolean IntWalk_IWalking::TestArretPassage(const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ TheIWFunction& sp,
+ math_Vector& UV,
+ Standard_Integer& Irang)
+
+// Umult et Vmult : table of stop (or crossing) points on border,
+// here only the crossing points are taken into account.
+// UV : the current point.
+// Irang : at exit : give index of the stop point in uvstart1 or 0.
+// consider that there is no risk of crossing only if there is one crossing point.
+
+// test of stop for an OPEN intersection line
+// 1) crossing test on all interior points
+// 2) stop test on all start points
+// if a stop is detected, the index of the stop point (Irang) is returned
+// in the iterator of start points and the associated parameters in UV space.
+{
+ Standard_Real Up, Vp, Du, Dv, Dup, Dvp, Utest, Vtest;
+ Standard_Integer j, N, ind;
+ Standard_Real tolu = tolerance(1);
+ Standard_Real tolv = tolerance(2);
+ Standard_Real tolu2 = 10. * tolerance(1);
+ Standard_Real tolv2 = 10. * tolerance(2);
+
+ Standard_Boolean Arrive = Standard_False;
+
+ // crossing test on point that can start a loop; mark
+ // as processed if passes through an open line
+
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(Up, Vp);
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(Up, Vp);
+ }
+
+ for (size_t i = 1; i < wd2.size(); i++)
+ {
+ if (wd2[i].etat > 0)
+ {
+ // debug jag 05.04.94
+
+ // if ((Up-wd2[i].ustart)*(UV(1)-wd2[i].ustart) +
+ // (Vp-wd2[i].vstart)*(UV(2)-wd2[i].vstart) <= 0)
+ Utest = wd2[i].ustart;
+ Vtest = wd2[i].vstart;
+
+ Du = UV(1) - Utest;
+ Dv = UV(2) - Vtest;
+ Dup = Up - Utest;
+ Dvp = Vp - Vtest;
+
+ //-- lbr le 30 oct 97
+
+ //IFV for OCC20285
+
+ if ((Abs(Du) < tolu2 && Abs(Dv) < tolv2) || (Abs(Dup) < tolu2 && Abs(Dvp) < tolv2))
+ {
+ wd2[i].etat = -wd2[i].etat;
+ }
+ else
+ {
+ Standard_Real DDu = (UV(1) - Up);
+ Standard_Real DDv = (UV(2) - Vp);
+ Standard_Real DDD = DDu * DDu + DDv * DDv;
+ Standard_Real DD1 = Du * Du + Dv * Dv;
+ if (DD1 <= DDD)
+ {
+ Standard_Real DD2 = Dup * Dup + Dvp * Dvp;
+ if (DD2 <= DDD && ((Du * Dup) + (Dv * Dvp * tolu / tolv) <= 0.))
+ {
+ wd2[i].etat = -wd2[i].etat;
+ }
+ }
+ }
+ }
+ }
+
+ // stop test on point given at input and not yet processed
+
+ // Modified by Sergey KHROMOV - Tue Nov 20 10:55:01 2001 Begin
+ // Check of all path points in the following order:
+ // * First check all not treated points;
+ // * After that check of already treated ones.
+ Standard_Integer l;
+
+ //// Modified by jgv, 28.07.2010 for OCC21914 ////
+ // There are several path points between (Up,Vp) and UV
+ // So several path points satisfy the condition
+ // Dup*UV1mUtest + Dvp*UV2mVtest) < 0
+ // We choose from them the path point with
+ // minimum distance to (Up,Vp)
+ TColStd_SequenceOfInteger i_candidates;
+ TColStd_SequenceOfReal SqDist_candidates;
+
+ for (l = 1; l <= 2 && !Arrive; l++)
+ {
+ Standard_Boolean isToCheck;
+
+ for (size_t i = 1; i < wd1.size(); i++)
+ {
+ if (l == 1)
+ isToCheck = (wd1[i].etat > 0);
+ else
+ isToCheck = (wd1[i].etat < 0);
+
+ if (isToCheck)
+ {
+ // Modified by Sergey KHROMOV - Tue Nov 20 11:03:16 2001 End
+
+ // debug jag voir avec isg
+
+ Utest = wd1[i].ustart;
+ Vtest = wd1[i].vstart;
+ Dup = Up - Utest;
+ Dvp = Vp - Vtest;
+ if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv)
+ {
+ Standard_Real UV1mUtest = UV(1) - Utest;
+ Standard_Real UV2mVtest = UV(2) - Vtest;
+ if (((Dup * UV1mUtest + Dvp * UV2mVtest) < 0) || (Abs(UV1mUtest) < tolu && Abs(UV2mVtest) < tolv))
+ {
+ i_candidates.Append((Standard_Integer)i);
+ SqDist_candidates.Append(Dup * Dup + Dvp * Dvp);
+ /*
+ Irang=i;
+ Arrive = Standard_True;
+ UV(1) = Utest;
+ UV(2) = Vtest;
+ */
+ }
+ else if (nbMultiplicities[i] > 0 && i_candidates.IsEmpty())
+ {
+ N = 0;
+ for (size_t k = 1; k < i; k++)
+ {
+ N += nbMultiplicities[k];
+ }
+ for (j = N + 1; j <= N + nbMultiplicities[i]; j++)
+ {
+ if (((Up - Umult(j)) * (UV(1) - Umult(j)) + (Vp - Vmult(j)) * (UV(2) - Vmult(j)) < 0)
+ || (Abs(UV(1) - Umult(j)) < tolu && Abs(UV(2) - Vmult(j)) < tolv))
+ {
+ Irang = (Standard_Integer)i;
+ Arrive = Standard_True;
+ UV(1) = Utest;
+ UV(2) = Vtest;
+ break;
+ }
+ }
+ }
+ if (Arrive)
+ {
+ Standard_Real abidF[1], abidD[1][2];
+ math_Vector bidF(abidF, 1, 1);
+ math_Matrix bidD(abidD, 1, 1, 1, 2);
+ sp.Values(UV, bidF, bidD);
+ break;
+ }
+ }
+ }
+ } //end of for (i = 1; i < wd1.size(); i++)
+ if (!i_candidates.IsEmpty())
+ {
+ Standard_Real MinSqDist = RealLast();
+ for (ind = 1; ind <= i_candidates.Length(); ind++)
+ if (SqDist_candidates(ind) < MinSqDist)
+ {
+ MinSqDist = SqDist_candidates(ind);
+ Irang = i_candidates(ind);
+ }
+ Arrive = Standard_True;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ }
+ } //end of for (l = 1; l <= 2 && !Arrive; l++)
+ return Arrive;
+}
+
+Standard_Boolean IntWalk_IWalking::TestArretPassage(const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const math_Vector& UV,
+ const Standard_Integer Index,
+ Standard_Integer& Irang)
+{
+ // Umult, Vmult : table of stop (or crossing) points on border, here
+ // only crossing points are taken into account.
+ // UV : the current point.
+ // Index : index of the start point in uvstart2 of the current line
+ // (this is an interior point).
+ // Irang : at output : gives the index of the point passing in uvstart1 or 0.
+ // consider that there is risk to cross only one crossing point.
+
+ // test of stop for a CLOSED intersection line.
+ // 1) test of crossing on all interior points.
+ // 2) test of crossing on all crossing points.
+
+ Standard_Real Up, Vp, Scal;
+ Standard_Boolean Arrive = Standard_False;
+ Standard_Integer N, k, i;
+ Standard_Real Utest, Vtest;
+ Standard_Real tolu = tolerance(1);
+ Standard_Real tolv = tolerance(2);
+
+ // tests of stop and of crossing on all interior points.
+
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(Up, Vp);
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(Up, Vp);
+ }
+
+ Standard_Real UV1 = UV(1);
+ Standard_Real UV2 = UV(2);
+
+ //Normalizing factor. If it is less than 1.0 then the range will be expanded.
+ //This is no good for computation. Therefore, it is limited.
+ //Do not limit this factor in case of highly anisotropic parametrization
+ //(parametric space is considerably larger in one direction than another).
+ const Standard_Boolean isHighlyAnisotropic = Max(tolu, tolv) > 1000. * Min(tolu, tolv);
+ const Standard_Real deltau = mySRangeU.IsVoid() ? UM - Um
+ : (isHighlyAnisotropic ? mySRangeU.Delta() : Max(mySRangeU.Delta(), 1.0));
+ const Standard_Real deltav = mySRangeV.IsVoid() ? VM - Vm
+ : (isHighlyAnisotropic ? mySRangeV.Delta() : Max(mySRangeV.Delta(), 1.0));
+
+ Up /= deltau;
+ UV1 /= deltau;
+ Vp /= deltav;
+ UV2 /= deltav;
+
+ tolu /= deltau;
+ tolv /= deltav;
+
+ Standard_Real tolu2 = tolu + tolu;
+ Standard_Real tolv2 = tolv + tolv;
+
+ Standard_Real dPreviousCurrent = (Up - UV1) * (Up - UV1) + (Vp - UV2) * (Vp - UV2);
+ for (k = 1; k < (int)wd2.size(); k++)
+ {
+ if (wd2[k].etat > 0)
+ {
+ Utest = wd2[k].ustart;
+ Vtest = wd2[k].vstart;
+
+ Utest /= deltau;
+ Vtest /= deltav;
+
+ Standard_Real UV1mUtest = UV1 - Utest;
+ Standard_Real UV2mVtest = UV2 - Vtest;
+ if ((UV1mUtest < tolu2 && UV1mUtest > -tolu2) && (UV2mVtest < tolv2 && UV2mVtest > -tolv2))
+ {
+ if (Index != k)
+ {
+ //-- cout<<"* etat2 : ("<<k<<")"<<endl;
+ wd2[k].etat = -wd2[k].etat; //-- mark the point as a crossing point
+ }
+ else
+ { //-- Index == k
+ //-- cout<<"* Arrive"<<endl;
+ Arrive = Standard_True;
+ }
+ }
+ else
+ {
+ Standard_Real UpmUtest = (Up - Utest);
+ Standard_Real VpmVtest = (Vp - Vtest);
+ Standard_Real dPreviousStart = (UpmUtest) * (UpmUtest) + (VpmVtest) * (VpmVtest);
+ Standard_Real dCurrentStart = UV1mUtest * UV1mUtest + UV2mVtest * UV2mVtest;
+
+ Scal = (UpmUtest) * (UV1mUtest) + (VpmVtest) * (UV2mVtest);
+ if ((Abs(UpmUtest) < tolu && Abs(VpmVtest) < tolv))
+ {
+ if (Index != k)
+ {
+ //-- cout<<"** etat2 : ("<<k<<")"<<endl;
+ wd2[k].etat = -wd2[k].etat;
+ }
+ }
+ else if (Scal < 0 && (dPreviousStart + dCurrentStart < dPreviousCurrent))
+ {
+ if (Index == k)
+ { // on a boucle.
+ Arrive = Standard_True;
+ //-- cout<<"** Arrive : k="<<k<<endl;
+ }
+ else
+ {
+ //-- cout<<"*** etat2 : ("<<k<<")"<<endl;
+ wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
+ }
+ }
+ else if (k != Index)
+ {
+ if (dPreviousStart < dPreviousCurrent * 0.25)
+ {
+ wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
+ //-- cout<<"**** etat2 : ("<<k<<")"<<endl;
+ }
+ else
+ {
+ if (dCurrentStart < dPreviousCurrent * 0.25)
+ {
+ //-- cout<<"***** etat2 : ("<<k<<")"<<endl;
+ wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
+ }
+ else
+ {
+ Standard_Real UMidUtest = 0.5 * (UV1 + Up) - Utest;
+ Standard_Real VMidVtest = 0.5 * (UV2 + Vp) - Vtest;
+ Standard_Real dMiddleStart = UMidUtest * UMidUtest + VMidVtest * VMidVtest;
+
+ if (dMiddleStart < dPreviousCurrent * 0.5)
+ {
+ //-- cout<<"*********** etat2 : ("<<k<<")"<<endl;
+ wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // crossing test on crossing points.
+
+ Irang = 0;
+ for (i = 1; i < (int)wd1.size(); i++)
+ {
+ if (wd1[i].etat > 0 && wd1[i].etat < 11)
+ { //test of crossing points
+ Utest = wd1[i].ustart;
+ Vtest = wd1[i].vstart;
+ Utest /= deltau;
+ Vtest /= deltav;
+
+ if (((Up - Utest) * (UV1 - Utest) + (Vp - Vtest) * (UV2 - Vtest) < 0)
+ || (Abs(UV1 - Utest) < tolu && Abs(UV2 - Vtest) < tolv))
+ Irang = i;
+ else if (nbMultiplicities[i] > 0)
+ {
+ N = 0;
+ for (k = 1; k < i; k++)
+ N = N + nbMultiplicities[k];
+ for (Standard_Integer j = N + 1; j <= N + nbMultiplicities[i]; j++)
+ {
+ Standard_Real Umultj = Umult(j) / deltau;
+ Standard_Real Vmultj = Vmult(j) / deltav;
+ if (((Up - Umultj) * (UV1 - Umultj) + (Vp - Vmultj) * (UV2 - Vmultj) < 0)
+ || (Abs(UV1 - Umultj) < tolu && Abs(UV2 - Vmultj) < tolv))
+ {
+ Irang = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return Arrive;
+}
+
+Standard_Boolean IntWalk_IWalking::TestArretAjout(TheIWFunction& sp,
+ math_Vector& UV,
+ Standard_Integer& Irang,
+ IntSurf_PntOn2S& Psol)
+
+// test of stop on added points
+// these are the points on the natural biorder that were not given at input
+// return : Psol, the added point.
+// Irang, index in the iterator of added points.
+// UV, parameter of the added point.
+//
+{
+ Standard_Boolean Arrive = Standard_False;
+ Standard_Real U1, V1;
+ Standard_Real Up, Vp;
+
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(Up, Vp);
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(Up, Vp);
+ }
+
+ Standard_Integer nbAjout = seqAjout.Length();
+ for (Standard_Integer i = 1; i <= nbAjout; i++)
+ {
+ Irang = seqAjout.Value(i);
+
+ // add test Abs(Irang) <= lines.Length() for the case when
+ // a closed line is opened by adding a 1 point on this same
+ // line. Anyway there is a huge problem as 2 points will be
+ // added on this line...
+
+ if (Abs(Irang) <= lines.Length())
+ {
+ const Handle(IntWalk_TheIWLine)& Line = lines.Value(Abs(Irang));
+ if (Irang > 0)
+ Psol = Line->Value(Line->NbPoints());
+ else
+ Psol = Line->Value(1);
+ if (!reversed)
+ {
+ Psol.ParametersOnS2(U1, V1);
+ }
+ else
+ {
+ Psol.ParametersOnS1(U1, V1);
+ }
+ if (((Up - U1) * (UV(1) - U1) + (Vp - V1) * (UV(2) - V1)) < 0
+ || (Abs(UV(1) - U1) < tolerance(1) && Abs(UV(2) - V1) < tolerance(2)))
+ {
+ //jag 940615 Irang= -Abs(Irang);
+ Arrive = Standard_True;
+ UV(1) = U1;
+ UV(2) = V1;
+ Standard_Real abidF[1], abidD[1][2];
+ math_Vector bidF(abidF, 1, 1);
+ math_Matrix bidD(abidD, 1, 1, 1, 2);
+ sp.Values(UV, bidF, bidD);
+ break;
+ }
+ }
+ }
+ return Arrive;
+}
+
+void IntWalk_IWalking::FillPntsInHoles(TheIWFunction& sp,
+ TColStd_SequenceOfInteger& CopySeqAlone,
+ IntSurf_SequenceOfInteriorPoint& PntsInHoles)
+{
+ math_Vector BornInf(1, 2), BornSup(1, 2);
+ BornInf(1) = Um;
+ BornSup(1) = UM;
+ BornInf(2) = Vm;
+ BornSup(2) = VM;
+ PointLineLine.Clear();
+ TColStd_SequenceOfInteger SeqToRemove;
+ TColStd_MapOfInteger BadSolutions;
+
+ for (Standard_Integer i = 1; i < CopySeqAlone.Length(); i++)
+ {
+ Standard_Integer Irang1 = CopySeqAlone(i);
+ if (Irang1 == 0)
+ continue;
+ Standard_Boolean ToRemove = Standard_False;
+ IntSurf_PntOn2S PointAlone1, PointAlone2;
+ const Handle(IntWalk_TheIWLine)& Line1 = lines.Value(Abs(Irang1));
+ if (Irang1 > 0)
+ PointAlone1 = Line1->Value(Line1->NbPoints());
+ else
+ PointAlone1 = Line1->Value(1);
+ gp_Pnt2d P2d1 = PointAlone1.ValueOnSurface(reversed), P2d2;
+ Standard_Real MinSqDist = RealLast();
+ Standard_Integer MinRang = 0, MinIndex = 0;
+ for (Standard_Integer j = i + 1; j <= CopySeqAlone.Length(); j++)
+ {
+ Standard_Integer Irang2 = CopySeqAlone(j);
+ if (Irang2 == 0 || BadSolutions.Contains(Irang2))
+ continue;
+ const Handle(IntWalk_TheIWLine)& Line2 = lines.Value(Abs(Irang2));
+ if (Irang2 > 0)
+ PointAlone2 = Line2->Value(Line2->NbPoints());
+ else
+ PointAlone2 = Line2->Value(1);
+ P2d2 = PointAlone2.ValueOnSurface(reversed);
+ Standard_Real aSqDist = P2d1.SquareDistance(P2d2);
+ if (aSqDist < MinSqDist)
+ {
+ MinSqDist = aSqDist;
+ MinRang = Irang2;
+ MinIndex = j;
+ }
+ }
+ //processing points from Irang1 and MinRang
+ if (MinRang == 0)
+ {
+ SeqToRemove.Append(Irang1);
+ BadSolutions.Clear();
+ continue;
+ }
+ //Ends of same line
+ if (Abs(Irang1) == Abs(MinRang) && lines.Value(Abs(Irang1))->NbPoints() == 2)
+ {
+ SeqToRemove.Append(Irang1);
+ SeqToRemove.Append(MinRang);
+ CopySeqAlone(i) = 0;
+ CopySeqAlone(MinIndex) = 0;
+ BadSolutions.Clear();
+ continue;
+ }
+ ///////////////////
+ const Handle(IntWalk_TheIWLine)& Line2 = lines.Value(Abs(MinRang));
+ if (MinRang > 0)
+ PointAlone2 = Line2->Value(Line2->NbPoints());
+ else
+ PointAlone2 = Line2->Value(1);
+ gp_Pnt Pnt1 = PointAlone1.Value();
+ gp_Pnt Pnt2 = PointAlone2.Value();
+ P2d2 = PointAlone2.ValueOnSurface(reversed);
+ Standard_Real MinSqDist3d = Pnt1.SquareDistance(Pnt2);
+ if (MinSqDist3d <= epsilon
+ || (Abs(P2d1.X() - P2d2.X()) <= tolerance(1) && Abs(P2d1.Y() - P2d2.Y()) <= tolerance(2))) //close points
+ ToRemove = Standard_True;
+ else //real curve
+ {
+ math_Vector UVap(1, 2), UV(1, 2);
+ UVap(1) = (P2d1.X() + P2d2.X()) / 2;
+ UVap(2) = (P2d1.Y() + P2d2.Y()) / 2;
+ math_FunctionSetRoot Rsnld(sp, tolerance);
+ Rsnld.Perform(sp, UVap, BornInf, BornSup);
+ if (Rsnld.IsDone() && Abs(sp.Root()) <= sp.Tolerance() && !sp.IsTangent())
+ {
+ Rsnld.Root(UV);
+ gp_Pnt2d Pmid(UV(1), UV(2));
+ gp_Vec2d P1P2(P2d1, P2d2);
+ gp_Vec2d P1Pmid(P2d1, Pmid);
+ gp_Vec2d P2Pmid(P2d2, Pmid);
+ Standard_Real ScalProd1 = P1P2 * P1Pmid;
+ Standard_Real ScalProd2 = P1P2 * P2Pmid;
+ Standard_Boolean IsPmidValid = (ScalProd1 > 0. && ScalProd2 < 0); //Pmid is in the middle
+ if (IsPmidValid)
+ {
+ for (Standard_Integer iline = 1; iline <= lines.Length(); iline++)
+ if (IsPointOnLine(Pmid, iline))
+ {
+ IsPmidValid = Standard_False;
+ break;
+ }
+ }
+ if (IsPmidValid)
+ {
+ IntSurf_InteriorPoint aPoint(sp.Point(), UV(1), UV(2), sp.Direction3d(), sp.Direction2d());
+ PntsInHoles.Append(aPoint);
+ TColStd_ListOfInteger LineLine;
+ LineLine.Append(Irang1);
+ LineLine.Append(MinRang);
+ PointLineLine.Bind(PntsInHoles.Length(), LineLine);
+ }
+ else
+ {
+ BadSolutions.Add(MinRang);
+ i--;
+ continue;
+ }
+ }
+ else
+ {
+ BadSolutions.Add(MinRang);
+ i--;
+ continue;
+ }
+ }
+ CopySeqAlone(i) = 0;
+ CopySeqAlone(MinIndex) = 0;
+ if (ToRemove)
+ {
+ SeqToRemove.Append(Irang1);
+ SeqToRemove.Append(MinRang);
+ }
+ BadSolutions.Clear();
+ }
+
+ for (Standard_Integer i = 1; i <= SeqToRemove.Length(); i++)
+ for (Standard_Integer j = 1; j <= seqAlone.Length(); j++)
+ if (seqAlone(j) == SeqToRemove(i))
+ {
+ seqAlone.Remove(j);
+ break;
+ }
+}
+
+void IntWalk_IWalking::TestArretCadre(const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const Handle(IntWalk_TheIWLine)& Line,
+ TheIWFunction& sp,
+ math_Vector& UV,
+ Standard_Integer& Irang)
+
+// test of stop when located on border.
+// tried all tests of stop and arrived.
+// test of stop on all given departure points already marked and on the entire current line.
+// This line can be shortened if the stop point is found.
+// Abs(Irang) = index in the iterator of departure points or 0
+// if Irang <0 , it is necessary to add this point on the line (no Line->Cut)
+// UV = parameter of the departure point
+{
+ Standard_Real Scal, Up, Vp, Uc, Vc;
+ Standard_Integer N;
+ Standard_Boolean Found = Standard_False;
+
+ Irang = 0;
+ for (Standard_Integer i = 1; i < (int)wd1.size(); i++)
+ {
+ if (wd1[i].etat < 0)
+ {
+ N = 0; // range in UVMult.
+ if (nbMultiplicities[i] > 0)
+ {
+ for (Standard_Integer k = 1; k < i; k++)
+ N += nbMultiplicities[k];
+ }
+ if (!reversed)
+ {
+ Line->Value(1).ParametersOnS2(Up, Vp);
+ }
+ else
+ {
+ Line->Value(1).ParametersOnS1(Up, Vp);
+ }
+ Standard_Integer nbp = Line->NbPoints();
+ for (Standard_Integer j = 2; j <= nbp; j++)
+ {
+ if (!reversed)
+ {
+ Line->Value(j).ParametersOnS2(Uc, Vc);
+ }
+ else
+ {
+ Line->Value(j).ParametersOnS1(Uc, Vc);
+ }
+
+ gp_Vec2d aVec1(Up - wd1[i].ustart, Vp - wd1[i].vstart), aVec2(Uc - wd1[i].ustart, Vc - wd1[i].vstart);
+ CutVectorByTolerances(aVec1, tolerance);
+ CutVectorByTolerances(aVec2, tolerance);
+
+ Scal = aVec1 * aVec2;
+
+ // if a stop point is found: stop the line on this point.
+ if (Scal < 0)
+ {
+ Line->Cut(j);
+ nbp = Line->NbPoints();
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ }
+ else if (Abs(Uc - wd1[i].ustart) < tolerance(1) && Abs(Vc - wd1[i].vstart) < tolerance(2))
+ {
+ Line->Cut(j);
+ nbp = Line->NbPoints();
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ }
+ else if (nbMultiplicities[i] > 0)
+ {
+ for (Standard_Integer k = N + 1; k <= N + nbMultiplicities[i]; k++)
+ {
+ aVec1.SetCoord(Up - Umult(k), Vp - Vmult(k)), aVec2.SetCoord(Uc - Umult(k), Vc - Vmult(k));
+ CutVectorByTolerances(aVec1, tolerance);
+ CutVectorByTolerances(aVec2, tolerance);
+
+ Scal = aVec1 * aVec2;
+
+ if (Scal < 0)
+ {
+ Line->Cut(j);
+ nbp = Line->NbPoints();
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ break;
+ }
+ else if (Abs(Uc - Umult(k)) < tolerance(1) && Abs(Vc - Vmult(k)) < tolerance(2))
+ {
+ Line->Cut(j);
+ nbp = Line->NbPoints();
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ break;
+ }
+ }
+ }
+ if (Found)
+ {
+ Standard_Real abidF[1], abidD[1][2];
+ math_Vector bidF(abidF, 1, 1);
+ math_Matrix bidD(abidD, 1, 1, 1, 2);
+ sp.Values(UV, bidF, bidD);
+ Standard_Integer NBP = Line->NbPoints();
+ Standard_Integer Indextg;
+ Line->TangentVector(Indextg);
+ if (Indextg > NBP)
+ {
+ if (j > 3 && j <= NBP + 1)
+ {
+ gp_Vec Dir3d = sp.Direction3d();
+ gp_Vec Dir3d1 = gp_Vec(Line->Value(j - 2).Value(), Line->Value(j - 1).Value());
+ Standard_Real dot = Dir3d.Dot(Dir3d1);
+ if (dot < 0.0)
+ { // Normally this Function should not be used often !!!
+ Dir3d.Reverse();
+ //-- cout<<" IntWalk_IWalking_2.gxx REVERSE "<<endl;
+ }
+ Line->SetTangentVector(previousd3d, j - 1);
+ }
+#ifdef OCCT_DEBUG
+ else
+ {
+ std::cout << " IntWalk_IWalking_2.gxx : bizarrerie 30 10 97 " << std::endl;
+ }
+#endif
+ }
+
+ return;
+ }
+ Up = Uc;
+ Vp = Vc;
+ }
+
+ // now the last point of the line and the last calculated point are compated.
+ // there will be no need to "Cut"
+
+ gp_Vec2d aVec1(Up - wd1[i].ustart, Vp - wd1[i].vstart), aVec2(UV(1) - wd1[i].ustart, UV(2) - wd1[i].vstart);
+ CutVectorByTolerances(aVec1, tolerance);
+ CutVectorByTolerances(aVec2, tolerance);
+
+ Scal = aVec1 * aVec2;
+
+ if (Scal < 0)
+ {
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ }
+ else if (Abs(UV(1) - wd1[i].ustart) < tolerance(1) && Abs(UV(2) - wd1[i].vstart) < tolerance(2))
+ {
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ }
+ else if (nbMultiplicities[i] > 0)
+ {
+ for (Standard_Integer j = N + 1; j <= N + nbMultiplicities[i]; j++)
+ {
+ aVec1.SetCoord(Up - Umult(j), Vp - Vmult(j));
+ aVec2.SetCoord(UV(1) - Umult(j), UV(2) - Vmult(j));
+ CutVectorByTolerances(aVec1, tolerance);
+ CutVectorByTolerances(aVec2, tolerance);
+
+ Scal = aVec1 * aVec2;
+
+ if (Scal < 0)
+ {
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ break;
+ }
+ else if (Abs(UV(1) - Umult(j)) < tolerance(1) && Abs(UV(2) - Vmult(j)) < tolerance(2))
+ {
+ Irang = i;
+ UV(1) = wd1[Irang].ustart;
+ UV(2) = wd1[Irang].vstart;
+ Found = Standard_True;
+ break;
+ }
+ }
+ }
+ if (Found)
+ {
+ Irang = -Irang; // jag 941017
+ Standard_Real abidF[1], abidD[1][2];
+ math_Vector bidF(abidF, 1, 1);
+ math_Matrix bidD(abidD, 1, 1, 1, 2);
+ sp.Values(UV, bidF, bidD);
+ return;
+ }
+ }
+ }
+}
+
+//-- IntWalk_IWalking_3.gxx
+
+// modified by NIZHNY-MKK Thu Nov 2 15:07:26 2000.BEGIN
+static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
+ const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const Standard_Real& prevUp,
+ const Standard_Real& prevVp,
+ const IntWalk_VectorOfInteger& nbMultiplicities,
+ const math_Vector& tolerance,
+ TheIWFunction& sp,
+ math_Vector& UV,
+ Standard_Integer& Irang);
+// modified by NIZHNY-MKK Thu Nov 2 15:07:39 2000.END
+
+void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const ThePOPIterator& Pnts1,
+ TheIWFunction& Func,
+ Standard_Boolean& Rajout)
+
+// Processing of open line.
+//
+// 1) for any starting point, which is not passing and not tangent and not yet processed,
+// calculation of the step of advancement = step depending on the arrow and the maximum step.
+//
+// 2) calculate a point of approach (this point is on the tangent to the section
+// of distance = no point in the interior)
+//
+// 3) conditions {
+// (all calculated points do not exceed a point in the
+// list of starting points)
+// or
+// (all points do not form an open line going
+// from one border of the domain to the other or from a point tangent
+// to border or from 2 tangent points : single cases)
+//
+// 1) framing of approached point on borders if necessary (there is
+// calculation of step)
+// 2) calculation of the point
+// 3) if the point is not found the step is divided
+// 4) stop tests
+// 5) calculation of the step depending on the arrow and the max step,
+// (TestDeflection)
+// stop possible.
+// end of conditions.
+
+{
+ Standard_Integer I = 0, N = 0, SaveN = 0;
+ Standard_Real aBornInf[2] = {}, aBornSup[2] = {}, aUVap[2] = {};
+ math_Vector BornInf(aBornInf, 1, 2), BornSup(aBornSup, 1, 2), UVap(aUVap, 1, 2);
+ Standard_Real PasC = 0.0, PasCu = 0.0, PasCv = 0.0;
+ Standard_Boolean Arrive = false; // shows if the line ends
+ Standard_Boolean Cadre = false; // shows if one is on border of the domain
+ Standard_Boolean ArretAjout = false; //shows if one is on added point
+ IntSurf_PntOn2S Psol;
+ Handle(IntWalk_TheIWLine) CurrentLine; // line under construction
+ Standard_Boolean Tgtend = false;
+
+ IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent = IntWalk_OK;
+
+ Standard_Integer NbDivision = 0;
+ // number of divisions of step for each section
+
+ Standard_Integer StepSign = 0;
+
+ ThePointOfPath PathPnt;
+
+ BornInf(1) = Um;
+ BornSup(1) = UM;
+ BornInf(2) = Vm;
+ BornSup(2) = VM;
+
+ math_FunctionSetRoot Rsnld(Func, tolerance);
+ Standard_Integer nbPath = Pnts1.Length();
+
+ // modified by NIZHNY-MKK Fri Oct 27 12:32:34 2000.BEGIN
+ NCollection_LocalArray<Standard_Integer> movementdirectioninfoarr(nbPath + 1);
+ Standard_Integer* movementdirectioninfo = movementdirectioninfoarr;
+ for (I = 0; I <= nbPath; I++)
+ {
+ movementdirectioninfo[I] = 0;
+ }
+ // modified by NIZHNY-MKK Fri Oct 27 12:32:38 2000.END
+
+ TheIWFunction aFuncForDuplicate = Func;
+
+ for (I = 1; I <= nbPath; I++)
+ {
+ //start point of the progression
+ // if (wd1[I].etat > 11) {
+ // modified by NIZHNY-MKK Fri Oct 27 12:33:37 2000.BEGIN
+ if ((wd1[I].etat > 11) || ((wd1[I].etat < -11) && (movementdirectioninfo[I] != 0)))
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 12:33:43 2000.END
+ PathPnt = Pnts1.Value(I);
+ UVap(1) = wd1[I].ustart;
+ UVap(2) = wd1[I].vstart;
+ MakeWalkingPoint(11, UVap(1), UVap(2), Func, previousPoint);
+
+ if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
+ {
+ wd1[I].etat = -Abs(wd1[I].etat); //mark point as processed
+ continue;
+ }
+
+ CurrentLine = new IntWalk_TheIWLine(new NCollection_IncAllocator());
+ CurrentLine->SetTangencyAtBegining(Standard_False);
+ Tgtend = Standard_False;
+ CurrentLine->AddStatusFirst(Standard_False, Standard_True, I, PathPnt);
+ previousd3d = Func.Direction3d();
+ previousd2d = Func.Direction2d();
+ CurrentLine->AddPoint(previousPoint);
+ // modified by NIZHNY-MKK Fri Oct 27 12:34:32 2000.BEGIN
+ if (movementdirectioninfo[I] != 0)
+ {
+ if (movementdirectioninfo[I] < 0)
+ {
+ StepSign = -1;
+ CurrentLine->SetTangentVector(previousd3d.Reversed(), 1);
+ }
+ else
+ {
+ StepSign = 1;
+ CurrentLine->SetTangentVector(previousd3d, 1);
+ }
+ }
+ else
+ {
+ Standard_Real tyutuyt = ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
+ if (tyutuyt < 0)
+ {
+ StepSign = -1;
+ CurrentLine->SetTangentVector(previousd3d.Reversed(), 1);
+ }
+ else
+ {
+ StepSign = 1;
+ CurrentLine->SetTangentVector(previousd3d, 1);
+ }
+ }
+ // modified by NIZHNY-MKK Fri Oct 27 12:34:37 2000.END
+
+ // Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
+ wd1[I].etat = -Abs(wd1[I].etat);
+ movementdirectioninfo[I] = (movementdirectioninfo[I] == 0) ? StepSign : 0;
+ // Modified by Sergey KHROMOV - Tue Nov 20 10:41:56 2001 End
+ // first step of advancement
+ Standard_Real d2dx = Abs(previousd2d.X());
+ Standard_Real d2dy = Abs(previousd2d.Y());
+ if (d2dx < tolerance(1))
+ {
+ PasC = pas * (VM - Vm) / d2dy;
+ }
+ else if (d2dy < tolerance(2))
+ {
+ PasC = pas * (UM - Um) / d2dx;
+ }
+ else
+ {
+ PasC = pas * Min((UM - Um) / d2dx, (VM - Vm) / d2dy);
+ }
+
+ Arrive = Standard_False;
+ ArretAjout = Standard_False;
+ NbDivision = 0;
+ StatusPrecedent = IntWalk_OK;
+ // modified by NIZHNY-MKK Fri Oct 27 12:39:37 2000
+ Standard_Integer IndexOfPathPointDoNotCheck = 0;
+ Standard_Integer aNbIter = 10;
+ while (!Arrive)
+ { // as one of stop tests is not checked
+ Cadre = Cadrage(BornInf, BornSup, UVap, PasC, StepSign);
+ // Border?
+
+#ifdef CHRONO
+ Chronrsnld.Start();
+#endif
+
+ Rsnld.Perform(Func, UVap, BornInf, BornSup);
+
+#ifdef CHRONO
+ Chronrsnld.Stop();
+#endif
+
+ if (Cadre)
+ {
+ BornInf(1) = Um;
+ BornSup(1) = UM;
+ BornInf(2) = Vm;
+ BornSup(2) = VM;
+ }
+ if (Rsnld.IsDone())
+ {
+ if (Abs(Func.Root()) > Func.Tolerance())
+ {
+ PasC = PasC / 2.0;
+ PasCu = Abs(PasC * previousd2d.X());
+ PasCv = Abs(PasC * previousd2d.Y());
+ if (PasCu <= tolerance(1) && PasCv <= tolerance(2))
+ {
+ if (CurrentLine->NbPoints() == 1)
+ break;
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True; // check
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+ else
+ { // test stop
+ Rsnld.Root(UVap);
+ Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
+ if (Arrive)
+ {
+ Cadre = Standard_False;
+ //in case if there is a frame and arrive at the same time
+ }
+ else
+ {
+ if (Rajout)
+ {
+ ArretAjout = TestArretAjout(Func, UVap, N, Psol);
+ SaveN = N;
+ if (ArretAjout)
+ {
+ // jag 940615
+ Tgtend = lines.Value(N)->IsTangentAtEnd();
+ N = -N;
+ }
+ }
+ // modified by NIZHNY-MKK Thu Nov 2 15:09:08 2000.BEGIN
+ if (!(Rajout && ArretAjout))
+ {
+ Standard_Real prevUp, prevVp;
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(prevUp, prevVp);
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(prevUp, prevVp);
+ }
+ Arrive = TestPassedSolutionWithNegativeState(wd1,
+ Umult,
+ Vmult,
+ prevUp,
+ prevVp,
+ nbMultiplicities,
+ tolerance,
+ Func,
+ UVap,
+ N);
+ if (Arrive)
+ {
+ Cadre = Standard_False;
+ }
+ }
+ // modified by NIZHNY-MKK Thu Nov 2 15:09:13 2000.END
+ if (!ArretAjout && Cadre)
+ {
+ if (CurrentLine->NbPoints() == 1)
+ break; // cancel the line
+ TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
+ // if (N == 0) {
+ if (N <= 0)
+ { // jag 941017
+ MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
+ Tgtend = Func.IsTangent();
+ N = -N;
+ }
+ }
+ }
+ aStatus = TestDeflection(Func, Arrive, UVap, StatusPrecedent, NbDivision, PasC, StepSign);
+ StatusPrecedent = aStatus;
+ if (aStatus == IntWalk_PasTropGrand)
+ {
+ Arrive = Standard_False;
+ ArretAjout = Standard_False;
+ Tgtend = Standard_False; // jag 940615
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(UVap(1), UVap(2));
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(UVap(1), UVap(2));
+ }
+ }
+ else if (ArretAjout || Cadre)
+ {
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ //if (aStatus != IntWalk_ArretSurPointPrecedent)
+ CurrentLine->AddPoint(Psol);
+ //Remove <SaveN> from <seqAlone>
+ for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
+ if (seqAlone(iseq) == SaveN)
+ {
+ seqAlone.Remove(iseq);
+ break;
+ }
+
+ if (Cadre && N == 0)
+ {
+ Rajout = Standard_True;
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+ else if (aStatus == IntWalk_ArretSurPointPrecedent)
+ {
+ if (CurrentLine->NbPoints() == 1)
+ { //cancel the line
+ Arrive = Standard_False;
+ break;
+ }
+ Arrive = Standard_True;
+ Rajout = Standard_True;
+ //AddAlonePoint();
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True; // check
+ }
+ else if (Arrive)
+ {
+ if (CurrentLine->NbPoints() == 1 && // cancel the line
+ (N == I || aStatus == IntWalk_PointConfondu))
+ {
+ // if N == I the main uv is probably lost
+ // or the point is a point of accumulation
+ // if point is confused the start data is bad
+ Arrive = Standard_False;
+ break;
+ }
+ // necessarily N > 0 jag 940617
+ // point of stop given at input
+ PathPnt = Pnts1.Value(N);
+
+ Standard_Integer etat1N = wd1[N].etat;
+ // modified by NIZHNY-MKK Thu Nov 2 15:09:51 2000.BEGIN
+ // if (etat1N < 11) { // passing point that is a stop
+ if (Abs(etat1N) < 11)
+ { // passing point that is a stop
+ // modified by NIZHNY-MKK Thu Nov 2 15:12:11 2000.END
+ if (aStatus == IntWalk_ArretSurPoint)
+ {
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True; // need check
+ }
+ else
+ {
+ Arrive = Standard_False;
+ }
+ CurrentLine->AddIndexPassing(N);
+ }
+ else
+ { // point of stop given at input
+ if (etat1N == 11)
+ {
+ Tgtend = Standard_True;
+ }
+ CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
+ }
+ AddPointInCurrentLine(N, PathPnt, CurrentLine);
+ if ((etat1N != 1 && etat1N != 11))
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 12:43:05 2000.BEGIN
+ // wd1[N].etat= - wd1[N].etat;
+ wd1[N].etat = -Abs(etat1N);
+ movementdirectioninfo[N] = (movementdirectioninfo[N] == 0) ? StepSign : 0;
+ if (Arrive && movementdirectioninfo[N] != 0)
+ {
+ IndexOfPathPointDoNotCheck = N;
+ }
+
+ if (Arrive)
+ {
+ Rajout = Standard_True;
+ seqAjout.Append(lines.Length() + 1);
+ }
+ // modified by NIZHNY-MKK Fri Oct 27 12:45:33 2000.END
+ }
+ }
+ else if (aStatus == IntWalk_ArretSurPoint)
+ {
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True;
+ MakeWalkingPoint(1, UVap(1), UVap(2), Func, Psol);
+ CurrentLine->AddPoint(Psol);
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ else if (aStatus == IntWalk_OK)
+ {
+ MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
+ previousd3d = Func.Direction3d();
+ previousd2d = Func.Direction2d();
+ CurrentLine->AddPoint(previousPoint);
+ }
+ else if (aStatus == IntWalk_PointConfondu)
+ {
+ aNbIter--;
+ }
+ }
+ }
+ else
+ { // no numerical solution
+ PasC = PasC / 2.;
+ PasCu = Abs(PasC * previousd2d.X());
+ PasCv = Abs(PasC * previousd2d.Y());
+ if (PasCu <= tolerance(1) && PasCv <= tolerance(2))
+ {
+ if (CurrentLine->NbPoints() == 1)
+ break;
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True; // need check
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+
+ if (aNbIter < 0)
+ break;
+ } // end of started line
+
+ if (Arrive)
+ {
+ CurrentLine->SetTangencyAtEnd(Tgtend);
+ lines.Append(CurrentLine);
+ // modified by NIZHNY-MKK Fri Oct 27 12:59:29 2000.BEGIN
+ movementdirectioninfo[I] = 0;
+ if (wd1[I].etat > 0)
+ // modified by NIZHNY-MKK Fri Oct 27 12:59:42 2000.END
+ wd1[I].etat = -wd1[I].etat;
+
+ //-- lbr le 5 juin 97 (Pb ds Contap)
+ for (Standard_Integer av = 1; av <= nbPath; av++)
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 13:00:22 2000.BEGIN
+ // if (wd1[av].etat > 11) {
+ if ((wd1[av].etat > 11)
+ || ((av != I) && (av != IndexOfPathPointDoNotCheck) && (wd1[av].etat < -11) && (movementdirectioninfo[av] != 0)))
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 13:00:26 2000.END
+ Standard_Real Uav = wd1[av].ustart;
+ Standard_Real Vav = wd1[av].vstart;
+ Standard_Real Uavp, Vavp;
+ const IntSurf_PntOn2S& avP = CurrentLine->Value(CurrentLine->NbPoints());
+ if (!reversed)
+ {
+ avP.ParametersOnS2(Uavp, Vavp);
+ }
+ else
+ {
+ avP.ParametersOnS1(Uavp, Vavp);
+ }
+ Uav -= Uavp;
+ Vav -= Vavp;
+ Uav *= 0.001;
+ Vav *= 0.001;
+ if (Abs(Uav) < tolerance(1) && Abs(Vav) < tolerance(2))
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 13:01:38 2000.BEGIN
+ // wd1[av].etat=-wd1[av].etat;
+ if (wd1[av].etat < 0)
+ {
+ movementdirectioninfo[av] = 0;
+ }
+ else
+ {
+ wd1[av].etat = -wd1[av].etat;
+ movementdirectioninfo[av] = StepSign;
+ }
+ // modified by NIZHNY-MKK Fri Oct 27 13:01:42 2000.END
+ CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
+ //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
+ }
+
+ const IntSurf_PntOn2S& avPP = CurrentLine->Value(1);
+ if (!reversed)
+ {
+ avPP.ParametersOnS2(Uavp, Vavp);
+ }
+ else
+ {
+ avPP.ParametersOnS1(Uavp, Vavp);
+ }
+ Uav = wd1[av].ustart;
+ Vav = wd1[av].vstart;
+ Uav -= Uavp;
+ Vav -= Vavp;
+ Uav *= 0.001;
+ Vav *= 0.001;
+ if (Abs(Uav) < tolerance(1) && Abs(Vav) < tolerance(2))
+ {
+ // modified by NIZHNY-MKK Fri Oct 27 13:02:49 2000.BEGIN
+ // wd1[av].etat=-wd1[av].etat;
+ if (wd1[av].etat < 0)
+ {
+ movementdirectioninfo[av] = 0;
+ }
+ else
+ {
+ wd1[av].etat = -wd1[av].etat;
+ movementdirectioninfo[av] = -StepSign;
+ }
+ // modified by NIZHNY-MKK Fri Oct 27 13:02:52 2000.END
+ //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
+ CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
+ }
+ }
+ }
+ }
+ } //end of point processing
+ } //end of all points
+}
+
+// modified by NIZHNY-MKK Thu Nov 2 15:07:53 2000.BEGIN
+static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
+ const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const Standard_Real& prevUp,
+ const Standard_Real& prevVp,
+ const IntWalk_VectorOfInteger& nbMultiplicities,
+ const math_Vector& tolerance,
+ TheIWFunction& sp,
+ math_Vector& UV,
+ Standard_Integer& Irang)
+{
+ Standard_Boolean Arrive = Standard_False;
+ Standard_Real Dup, Dvp, Utest, Vtest;
+ Standard_Real tolu = tolerance(1);
+ Standard_Real tolv = tolerance(2);
+ Standard_Integer i, j, k, N;
+ for (i = 1; i < (int)wd.size(); i++)
+ {
+ if (wd[i].etat < -11)
+ {
+ // debug jag see with isg
+
+ Utest = wd[i].ustart;
+ Vtest = wd[i].vstart;
+ Dup = prevUp - Utest;
+ Dvp = prevVp - Vtest;
+ if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv)
+ {
+ Standard_Real UV1mUtest = UV(1) - Utest;
+ Standard_Real UV2mVtest = UV(2) - Vtest;
+ if (((Dup * UV1mUtest + Dvp * UV2mVtest) < 0) || (Abs(UV1mUtest) < tolu && Abs(UV2mVtest) < tolv))
+ {
+ Irang = i;
+ Arrive = Standard_True;
+ UV(1) = Utest;
+ UV(2) = Vtest;
+ }
+ else if (nbMultiplicities[i] > 0)
+ {
+ N = 0;
+ for (k = 1; k < i; k++)
+ {
+ N += nbMultiplicities[k];
+ }
+ for (j = N + 1; j <= N + nbMultiplicities[i]; j++)
+ {
+ if (((prevUp - Umult(j)) * (UV(1) - Umult(j)) + (prevVp - Vmult(j)) * (UV(2) - Vmult(j)) < 0)
+ || (Abs(UV(1) - Umult(j)) < tolu && Abs(UV(2) - Vmult(j)) < tolv))
+ {
+ Irang = i;
+ Arrive = Standard_True;
+ UV(1) = Utest;
+ UV(2) = Vtest;
+ break;
+ }
+ }
+ }
+ if (Arrive)
+ {
+ Standard_Real abidF[1], abidD[1][2];
+ math_Vector bidF(abidF, 1, 1);
+ math_Matrix bidD(abidD, 1, 1, 1, 2);
+ sp.Values(UV, bidF, bidD);
+ break;
+ }
+ }
+ }
+ }
+ return Arrive;
+}
+// modified by NIZHNY-MKK Thu Nov 2 15:07:58 2000.END
+
+//-- IntWalk_IWalking_4.gxx
+
+void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
+ const TColStd_SequenceOfReal& Vmult,
+ const ThePOPIterator& Pnts1,
+ const ThePOLIterator& Pnts2,
+ TheIWFunction& Func,
+ Standard_Boolean& Rajout)
+// *********** Processing of closed line **********************
+//
+// for any interior non-processed point
+// calculate the step of advancement=step depending on the arrow and max step
+// calculate a point of approach (this point is on the tangent to the section
+// of distance = no interior point)
+// conditions
+// (all calculated points do not form a closed loop)
+// or
+// (all points do not form an open line going from
+// one border of the domain to the other or from a point tangent
+// to the border or from 2 tangent points : single cases)
+//
+// frame the point of approach on borders if necessary
+// calculate the point
+// if point not found divide the step
+// test of stop
+// calculate step depending on the arrow and the max step (stop possible)
+//
+// ********************************************************************
+{
+ Standard_Integer I = 0, N = 0, SaveN = 0;
+ Standard_Real aBornInf[2] = {}, aBornSup[2] = {}, aUVap[2] = {};
+ math_Vector BornInf(aBornInf, 1, 2), BornSup(aBornSup, 1, 2);
+ math_Vector Uvap(aUVap, 1, 2); // parameters of current approach
+ Standard_Real PasC = 0.0; // step of advancement on the tangent
+ Standard_Real PasCu = 0.0; // step of advancement current by U
+ Standard_Real PasCv = 0.0; // step of advancement current by V
+ Standard_Real PasSav = 0.0; // save first step of advancement
+ Standard_Boolean Arrive = false; // show if line ends
+ Standard_Boolean Cadre = false; // show if on border of the domains
+ Standard_Boolean ArretAjout = false; // show if on the added point
+ IntSurf_PntOn2S Psol;
+ Handle(IntWalk_TheIWLine) CurrentLine; //line under construction
+ ThePointOfPath PathPnt;
+ ThePointOfLoop LoopPnt;
+
+ Standard_Boolean Tgtbeg = false, Tgtend = false;
+
+ Standard_Integer StepSign = 0;
+
+ IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent;
+ Standard_Integer NbDivision = 0; // number of divisions of step
+ // during calculation of 1 section
+
+ Standard_Integer Ipass = 0;
+ //index in the iterator of points on edge of point of passage
+
+ BornInf(1) = Um;
+ BornSup(1) = UM;
+ BornInf(2) = Vm;
+ BornSup(2) = VM;
+
+ math_FunctionSetRoot Rsnld(Func, tolerance);
+ Standard_Integer nbLoop = Pnts2.Length();
+
+ // Check borders for degeneracy:
+ math_Matrix D(1, 1, 1, 2);
+ const Standard_Integer aNbSamplePnt = 10;
+ Standard_Boolean isLeftDegeneratedBorder[2] = {Standard_True, Standard_True};
+ Standard_Boolean isRightDegeneratedBorder[2] = {Standard_True, Standard_True};
+ math_Vector aStep(1, 2);
+ aStep = (BornSup - BornInf) / (aNbSamplePnt - 1);
+ for (Standard_Integer aBorderIdx = 1; aBorderIdx <= 2; aBorderIdx++)
+ {
+ Standard_Integer aChangeIdx = aBorderIdx == 2 ? 1 : 2;
+ math_Vector UV(1, 2);
+
+ // Left border.
+ UV(aBorderIdx) = BornInf(aBorderIdx);
+ for (Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
+ {
+ Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
+ UV(aChangeIdx) = aParam;
+ Func.Derivatives(UV, D);
+ if (Abs(D(1, aChangeIdx)) > Precision::Confusion())
+ {
+ isLeftDegeneratedBorder[aBorderIdx - 1] = Standard_False;
+ break;
+ }
+ }
+
+ // Right border.
+ UV(aBorderIdx) = BornSup(aBorderIdx);
+ for (Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
+ {
+ Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
+ UV(aChangeIdx) = aParam;
+ Func.Derivatives(UV, D);
+ if (Abs(D(1, aChangeIdx)) > Precision::Confusion())
+ {
+ isRightDegeneratedBorder[aBorderIdx - 1] = Standard_False;
+ break;
+ }
+ }
+ }
+
+ TheIWFunction aFuncForDuplicate = Func;
+
+ for (I = 1; I <= nbLoop; I++)
+ {
+ if (wd2[I].etat > 12)
+ { // start point of closed line
+ LoopPnt = Pnts2.Value(I);
+ previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt), reversed, wd2[I].ustart, wd2[I].vstart);
+
+ if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
+ {
+ wd2[I].etat = -wd2[I].etat; //mark point as processed
+ continue;
+ }
+
+ previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt);
+ previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt);
+
+ CurrentLine = new IntWalk_TheIWLine(new NCollection_IncAllocator());
+ CurrentLine->AddPoint(previousPoint);
+ CurrentLine->SetTangentVector(previousd3d, 1);
+ Tgtbeg = Standard_False;
+ Tgtend = Standard_False;
+ Uvap(1) = wd2[I].ustart;
+ Uvap(2) = wd2[I].vstart;
+
+ StepSign = 1;
+
+ // first step of advancement
+
+ Standard_Real d2dx = Abs(previousd2d.X());
+ Standard_Real d2dy = Abs(previousd2d.Y());
+ if (d2dx < tolerance(1))
+ {
+ PasC = pas * (VM - Vm) / d2dy;
+ }
+ else if (d2dy < tolerance(2))
+ {
+ PasC = pas * (UM - Um) / d2dx;
+ }
+ else
+ {
+ PasC = pas * Min((UM - Um) / d2dx, (VM - Vm) / d2dy);
+ }
+
+ PasSav = PasC;
+
+ Arrive = Standard_False;
+ ArretAjout = Standard_False;
+ NbDivision = 0;
+ StatusPrecedent = IntWalk_OK;
+ Standard_Integer aNbIter = 10;
+ while (!Arrive)
+ { // as no test of stop is passed
+ Cadre = Cadrage(BornInf, BornSup, Uvap, PasC, StepSign); // border?
+#ifdef CHRONO
+ Chronrsnld.Start();
+#endif
+
+ Rsnld.Perform(Func, Uvap, BornInf, BornSup);
+
+#ifdef CHRONO
+ Chronrsnld.Stop();
+#endif
+ Standard_Boolean isOnDegeneratedBorder = Standard_False;
+
+ if (Cadre)
+ { // update of limits.
+ BornInf(1) = Um;
+ BornSup(1) = UM;
+ BornInf(2) = Vm;
+ BornSup(2) = VM;
+ }
+ if (Rsnld.IsDone())
+ {
+ if (Abs(Func.Root()) > Func.Tolerance())
+ { // no solution for the tolerance
+ PasC = PasC / 2.;
+ PasCu = Abs(PasC * previousd2d.X());
+ PasCv = Abs(PasC * previousd2d.Y());
+
+ if (PasCu <= tolerance(1) && PasCv <= tolerance(2))
+ {
+ if (CurrentLine->NbPoints() == 1)
+ {
+ RemoveTwoEndPoints(I);
+ break; //cancel the line
+ }
+ if (wd2[I].etat > 12)
+ { //the line should become open
+ wd2[I].etat = 12; //declare it open
+ ArretAjout = Standard_False;
+ OpenLine(0, Psol, Pnts1, Func, CurrentLine);
+ StepSign = -1;
+ StatusPrecedent = IntWalk_OK;
+ Arrive = Standard_False;
+ PasC = PasSav;
+ Rajout = Standard_True;
+ seqAlone.Append(-lines.Length() - 1);
+ seqAjout.Append(-lines.Length() - 1);
+ }
+ else
+ { // line s is open
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ Tgtend = Standard_True;
+ }
+ /*
+ Arrive = Standard_True;
+ CurrentLine->AddStatusFirstLast(Standard_False,
+ Standard_False,Standard_False);
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length()+1);
+ seqAjout.Append(lines.Length()+1);
+ Tgtend = Standard_True;
+ */
+ }
+ }
+ else
+ { // there is a solution
+ Rsnld.Root(Uvap);
+
+ // Avoid uninitialized memory access.
+ if (CurrentLine->NbPoints() > 2)
+ {
+ for (Standard_Integer aCoordIdx = 1; aCoordIdx <= 2; aCoordIdx++)
+ {
+ // Check degenerated cases and fix if possible.
+ if ((isLeftDegeneratedBorder[aCoordIdx - 1]
+ && Abs(Uvap(aCoordIdx) - BornInf(aCoordIdx)) < Precision::PConfusion())
+ || (isRightDegeneratedBorder[aCoordIdx - 1]
+ && Abs(Uvap(aCoordIdx) - BornSup(aCoordIdx)) < Precision::PConfusion()))
+ {
+ Standard_Real uvprev[2], uv[2];
+ if (!reversed)
+ {
+ CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS2(uvprev[0], uvprev[1]);
+ CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS2(uv[0], uv[1]);
+ }
+ else
+ {
+ CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS1(uvprev[0], uvprev[1]);
+ CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS1(uv[0], uv[1]);
+ }
+
+ Standard_Real aScaleCoeff = 0.0;
+
+ // Avoid finite cycle which lead to stop computing iline.
+ if (aStatus != IntWalk_PasTropGrand)
+ {
+ // Make linear extrapolation.
+ if (Abs(uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) > gp::Resolution())
+ aScaleCoeff = Abs((Uvap(aCoordIdx) - uv[aCoordIdx - 1]) / (uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]));
+ Standard_Integer aFixIdx = aCoordIdx == 1 ? 2 : 1; // Fixing index;
+ Uvap(aFixIdx) = uv[aFixIdx - 1] + (uv[aFixIdx - 1] - uvprev[aFixIdx - 1]) * aScaleCoeff;
+ isOnDegeneratedBorder = Standard_True;
+ }
+ }
+ }
+ }
+
+ Arrive = TestArretPassage(Umult, Vmult, Uvap, I, Ipass);
+ if (Arrive)
+ { //reset proper parameter to test the arrow.
+ Psol = CurrentLine->Value(1);
+ if (!reversed)
+ {
+ Psol.ParametersOnS2(Uvap(1), Uvap(2));
+ }
+ else
+ {
+ Psol.ParametersOnS1(Uvap(1), Uvap(2));
+ }
+ Cadre = Standard_False;
+ //in case if there is a frame and arrival at the same time
+ }
+ else
+ { // modif jag 940615
+ if (Rajout)
+ { // test on added points
+ ArretAjout = TestArretAjout(Func, Uvap, N, Psol);
+ SaveN = N;
+ if (ArretAjout)
+ {
+ if (N > 0)
+ {
+ Tgtend = lines.Value(N)->IsTangentAtEnd();
+ N = -N;
+ }
+ else
+ {
+ Tgtend = lines.Value(-N)->IsTangentAtBegining();
+ }
+ Arrive = (wd2[I].etat == 12);
+ }
+ }
+
+ if (!ArretAjout && Cadre)
+ { // test on already marked points
+ if (CurrentLine->NbPoints() == 1)
+ {
+ RemoveTwoEndPoints(I);
+ break; // cancel the line
+ }
+ TestArretCadre(Umult, Vmult, CurrentLine, Func, Uvap, N);
+ SaveN = N;
+ // if (N==0) {
+ if (N <= 0)
+ { // jag 941017
+ MakeWalkingPoint(2, Uvap(1), Uvap(2), Func, Psol);
+ Tgtend = Func.IsTangent(); // jag 940616
+ if (isOnDegeneratedBorder)
+ Tgtend = Standard_True;
+ N = -N;
+ }
+ Arrive = (wd2[I].etat == 12); // the line is open
+ }
+ }
+ aStatus = TestDeflection(Func, Arrive, Uvap, StatusPrecedent, NbDivision, PasC, StepSign);
+
+ if (isOnDegeneratedBorder && Tgtend)
+ aStatus = IntWalk_ArretSurPoint;
+
+ StatusPrecedent = aStatus;
+ if (aStatus == IntWalk_PasTropGrand)
+ { // division of the step
+ Arrive = Standard_False;
+ ArretAjout = Standard_False;
+ Tgtend = Standard_False; // jag 940616
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(Uvap(1), Uvap(2));
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(Uvap(1), Uvap(2));
+ }
+ }
+ else if (ArretAjout || Cadre)
+ {
+ if (Arrive)
+ { // line s is open
+ CurrentLine->AddStatusLast(Standard_False);
+ //if (aStatus != IntWalk_ArretSurPointPrecedent)
+ CurrentLine->AddPoint(Psol);
+
+ //Remove <SaveN> from <seqAlone> and, if it is first found point,
+ //from <seqAjout> too
+ if (IsValidEndPoint(I, SaveN))
+ {
+ for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
+ if (seqAlone(iseq) == SaveN)
+ {
+ seqAlone.Remove(iseq);
+ break;
+ }
+ if (CurrentLine->NbPoints() <= 3)
+ for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
+ if (seqAjout(iseq) == SaveN)
+ {
+ seqAjout.Remove(iseq);
+ break;
+ }
+ }
+ else
+ {
+ if (seqAlone.Last() == -lines.Length() - 1)
+ {
+ seqAlone.Remove(seqAlone.Length());
+ seqAjout.Remove(seqAjout.Length());
+ }
+ RemoveTwoEndPoints(I);
+ Arrive = Standard_False;
+ break; //cancel the line
+ }
+
+ if (Cadre && N == 0)
+ {
+ Rajout = Standard_True;
+ //seqAlone.Append(lines.Length()+1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+ else
+ { // open
+ wd2[I].etat = 12; // declare it open
+ Tgtbeg = Tgtend;
+ Tgtend = Standard_False;
+ ArretAjout = Standard_False;
+ StepSign = -1;
+ StatusPrecedent = IntWalk_OK;
+ PasC = PasSav;
+ //Check if <Psol> has been really updated
+ if (Arrive || Rajout || (!ArretAjout && Cadre && SaveN <= 0))
+ {
+ if (aStatus == IntWalk_ArretSurPointPrecedent)
+ {
+ CurrentLine->AddPoint(Psol);
+ OpenLine(0, Psol, Pnts1, Func, CurrentLine);
+ }
+ else
+ {
+ OpenLine(-lines.Length() - 1, Psol, Pnts1, Func, CurrentLine);
+ }
+ }
+ //Remove <SaveN> from <seqAlone> and, if it is first found point,
+ //from <seqAjout> too
+ if (IsValidEndPoint(I, SaveN))
+ {
+ for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
+ if (seqAlone(iseq) == SaveN)
+ {
+ seqAlone.Remove(iseq);
+ break;
+ }
+ if (CurrentLine->NbPoints() <= 2)
+ for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
+ if (seqAjout(iseq) == SaveN)
+ {
+ seqAjout.Remove(iseq);
+ break;
+ }
+ }
+ else
+ {
+ RemoveTwoEndPoints(I);
+ break; //cancel the line
+ }
+
+ if (Cadre && N == 0)
+ {
+ Rajout = Standard_True;
+ seqAjout.Append(-lines.Length() - 1);
+ }
+ }
+ }
+ else if (aStatus == IntWalk_ArretSurPointPrecedent)
+ {
+ if (CurrentLine->NbPoints() == 1)
+ { //cancel the line
+ Arrive = Standard_False;
+ RemoveTwoEndPoints(I);
+ break;
+ }
+ if (wd2[I].etat > 12)
+ { //the line should become open
+ wd2[I].etat = 12; //declare it open
+ ArretAjout = Standard_False;
+ OpenLine(0, Psol, Pnts1, Func, CurrentLine);
+ StepSign = -1;
+ StatusPrecedent = IntWalk_OK;
+ Arrive = Standard_False;
+ PasC = PasSav;
+ Rajout = Standard_True;
+ seqAlone.Append(-lines.Length() - 1);
+ seqAjout.Append(-lines.Length() - 1);
+ }
+ else
+ { // line s is open
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+ else if (Arrive)
+ {
+ if (wd2[I].etat > 12)
+ { //line closed good case
+ CurrentLine->AddStatusFirstLast(Standard_True, Standard_False, Standard_False);
+ CurrentLine->AddPoint(CurrentLine->Value(1));
+ }
+ else if ((N > 0) && (Pnts1.Length() >= N))
+ {
+ //point of stop given at input
+ PathPnt = Pnts1.Value(N);
+ CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
+ AddPointInCurrentLine(N, PathPnt, CurrentLine);
+ }
+ }
+ else if (aStatus == IntWalk_ArretSurPoint)
+ {
+ if (wd2[I].etat > 12)
+ { //line should become open
+ wd2[I].etat = 12; //declare it open
+ Tgtbeg = Standard_True;
+ Tgtend = Standard_False;
+ N = -lines.Length() - 1;
+ Psol.SetValue(Func.Point(), reversed, Uvap(1), Uvap(2));
+ OpenLine(N, Psol, Pnts1, Func, CurrentLine);
+ StepSign = -1;
+ Rajout = Standard_True;
+ seqAlone.Append(N);
+ seqAjout.Append(N);
+ StatusPrecedent = IntWalk_OK;
+ Arrive = Standard_False;
+ PasC = PasSav;
+ }
+ else
+ {
+ Arrive = Standard_True;
+ if (Ipass != 0)
+ { //point of passage, point of stop
+ PathPnt = Pnts1.Value(Ipass);
+ CurrentLine->AddStatusLast(Standard_True, Ipass, PathPnt);
+ AddPointInCurrentLine(Ipass, PathPnt, CurrentLine);
+ }
+ else
+ {
+ CurrentLine->AddStatusLast(Standard_False);
+ IntSurf_PntOn2S newP;
+ newP.SetValue(Func.Point(), reversed, Uvap(1), Uvap(2));
+ CurrentLine->AddPoint(newP);
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ }
+ }
+ else if (aStatus == IntWalk_OK)
+ {
+ if (Ipass != 0)
+ CurrentLine->AddIndexPassing(Ipass);
+ previousPoint.SetValue(Func.Point(), reversed, Uvap(1), Uvap(2));
+ previousd3d = Func.Direction3d();
+ previousd2d = Func.Direction2d();
+ CurrentLine->AddPoint(previousPoint);
+ }
+ else if (aStatus == IntWalk_PointConfondu)
+ {
+ aNbIter--;
+ }
+ }
+ }
+ else
+ { //no numerical solution NotDone
+ PasC = PasC / 2.;
+ PasCu = Abs(PasC * previousd2d.X());
+ PasCv = Abs(PasC * previousd2d.Y());
+
+ if (PasCu <= tolerance(1) && PasCv <= tolerance(2))
+ {
+ if (CurrentLine->NbPoints() == 1)
+ {
+ RemoveTwoEndPoints(I);
+ break; // cancel the line
+ }
+ if (wd2[I].etat > 12)
+ { //the line should become open
+ wd2[I].etat = 12; //declare it open
+ ArretAjout = Standard_False;
+ OpenLine(0, Psol, Pnts1, Func, CurrentLine);
+ StepSign = -1;
+ StatusPrecedent = IntWalk_OK;
+ Arrive = Standard_False;
+ PasC = PasSav;
+ Rajout = Standard_True;
+ seqAlone.Append(-lines.Length() - 1);
+ seqAjout.Append(-lines.Length() - 1);
+ }
+ else
+ { // line s is open
+ Arrive = Standard_True;
+ CurrentLine->AddStatusLast(Standard_False);
+ Tgtend = Standard_True;
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length() + 1);
+ seqAjout.Append(lines.Length() + 1);
+ }
+ /*
+ Arrive = Standard_True;
+ CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
+ Standard_False);
+ Tgtend = Standard_True;
+ Rajout = Standard_True;
+ seqAlone.Append(lines.Length()+1);
+ seqAjout.Append(lines.Length()+1);
+ */
+ }
+ }
+
+ if (aNbIter < 0)
+ break;
+ } // end of started line
+ if (Arrive)
+ {
+ CurrentLine->SetTangencyAtBegining(Tgtbeg);
+ CurrentLine->SetTangencyAtEnd(Tgtend);
+
+ lines.Append(CurrentLine);
+ wd2[I].etat = -wd2[I].etat; //mark point as processed
+ }
+ } //end of processing of start point
+ } //end of all start points
+}
+
+//-- IntWalk_IWalking_5.gxx
+
+namespace
+{
+ static const Standard_Real CosRef3D = 0.98; // rule by tests in U4
+ // correspond to 11.478 d
+ static const Standard_Real CosRef2D = 0.88; // correspond to 25 d
+ static const Standard_Integer MaxDivision = 60; // max number of step division
+ // because the angle is too great in 2d (U4)
+}
+
+IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection(TheIWFunction& sp,
+ const Standard_Boolean Finished,
+ const math_Vector& UV,
+ const IntWalk_StatusDeflection StatusPrecedent,
+ Standard_Integer& NbDivision,
+ Standard_Real& Step,
+ const Standard_Integer StepSign)
+{
+ // Check the step of advancement, AND recalculate this step :
+ //
+ // 1) test point confused
+ // if yes other tests are not done
+ // 2) test angle 3d too great
+ // if yes divide the step and leave
+ // angle3d = angle ((previous point, calculated point),
+ // previous tangent)
+ // 3) check step of advancement in 2d
+ // 4) test point confused
+ // 5) test angle 2d too great
+ // 6) test point of tangency
+ // if yes leave
+ // 7) calculate the tangent by u,v of the section
+ // 8) test angle 3d too great
+ // angle3d = angle ((previous point, calculated point),
+ // new tangent)
+ // 9) test angle 2d too great
+ //10) test change of side (pass the tangent point not knowing it)
+ //11) calculate the step of advancement depending on the vector
+ //12) adjust the step depending on the previous steps
+
+ IntWalk_StatusDeflection aStatus = IntWalk_OK;
+
+ //---------------------------------------------------------------------------------
+ //-- lbr le 4 Avril 95 : it is possible that the status returns points confused
+ //-- if epsilon is great enough (1e-11). In this case one loops
+ //-- without ever changing the values sent to Rsnld.
+ //---------------------------------------------------------------------------------
+ Standard_Real Paramu = 0.0, Paramv = 0.0;
+
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(Paramu, Paramv);
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(Paramu, Paramv);
+ }
+
+ const Standard_Real Du = UV(1) - Paramu;
+ const Standard_Real Dv = UV(2) - Paramv;
+ const Standard_Real Duv = Du * Du + Dv * Dv;
+
+ gp_Vec Corde(previousPoint.Value(), sp.Point());
+
+ const Standard_Real Norme = Corde.SquareMagnitude();
+
+ if ((Norme <= 4.0 * Precision::SquareConfusion())
+ && ((Duv <= Precision::SquarePConfusion()) || (StatusPrecedent != IntWalk_OK)))
+ { // the square is already taken in the constructor
+ aStatus = IntWalk_PointConfondu;
+ if (StatusPrecedent == IntWalk_PasTropGrand)
+ {
+ return IntWalk_ArretSurPointPrecedent;
+ }
+ }
+ else
+ {
+ Standard_Real Cosi = Corde * previousd3d;
+ Standard_Real Cosi2 = 0.0;
+
+ if (Cosi * StepSign >= 0.)
+ { // angle 3d <= pi/2 !!!!
+ const Standard_Real aDiv = previousd3d.SquareMagnitude() * Norme;
+ if (aDiv == 0)
+ return aStatus;
+ Cosi2 = Cosi * Cosi / aDiv;
+ }
+ if (Cosi2 < CosRef3D)
+ { //angle 3d too great
+ Step = Step / 2.0;
+ Standard_Real StepU = Abs(Step * previousd2d.X()), StepV = Abs(Step * previousd2d.Y());
+ if (StepU < tolerance(1) && StepV < tolerance(2))
+ aStatus = IntWalk_ArretSurPointPrecedent;
+ else
+ aStatus = IntWalk_PasTropGrand;
+ return aStatus;
+ }
+ }
+
+ const Standard_Real aMinTolU = 0.1 * Abs(Step * previousd2d.X()), aMinTolV = 0.1 * Abs(Step * previousd2d.Y());
+ const Standard_Real aTolU = (aMinTolU > 0.0) ? Min(tolerance(1), aMinTolU) : tolerance(1),
+ aTolV = (aMinTolV > 0.0) ? Min(tolerance(2), aMinTolV) : tolerance(2);
+
+ //If aMinTolU==0.0 then (Abs(Du) < aMinTolU) is equivalent of (Abs(Du) < 0.0).
+ //It is impossible. Therefore, this case should be processed separately.
+ //Analogically for aMinTolV.
+
+ if ((Abs(Du) < aTolU) && (Abs(Dv) < aTolV))
+ {
+ //Thin shapes (for which Ulast-Ufirst or/and Vlast-Vfirst is quite small)
+ //exists (see bug #25820). In this case, step is quite small too.
+ //Nevertheless, it not always means that we mark time. Therefore, Du and Dv
+ //must consider step (aMinTolU and aMinTolV parameters).
+
+ return IntWalk_ArretSurPointPrecedent; //confused point 2d
+ }
+
+ Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
+
+ if (Cosi < 0 && aStatus == IntWalk_PointConfondu)
+ return IntWalk_ArretSurPointPrecedent; // leave as step back
+ // with confused point
+
+ if (sp.IsTangent())
+ return IntWalk_ArretSurPoint;
+
+ //if during routing one has subdivided more than MaxDivision for each
+ //previous step, bug on the square; do nothing (experience U4)
+
+ if ((NbDivision < MaxDivision) && (aStatus != IntWalk_PointConfondu) && (StatusPrecedent != IntWalk_PointConfondu))
+ {
+ Standard_Real Cosi2 = Cosi * Cosi / Duv;
+ if (Cosi2 < CosRef2D || Cosi < 0)
+ {
+ Step = Step / 2.0;
+ Standard_Real StepU = Abs(Step * previousd2d.X()), StepV = Abs(Step * previousd2d.Y());
+
+ if (StepU < tolerance(1) && StepV < tolerance(2))
+ aStatus = IntWalk_ArretSurPointPrecedent;
+ else
+ aStatus = IntWalk_PasTropGrand;
+ NbDivision = NbDivision + 1;
+ return aStatus;
+ }
+
+ Cosi = Corde * sp.Direction3d();
+ Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
+ if (Cosi2 < CosRef3D)
+ { //angle 3d too great
+ Step = Step / 2.;
+ Standard_Real StepU = Abs(Step * previousd2d.X()), StepV = Abs(Step * previousd2d.Y());
+ if (StepU < tolerance(1) && StepV < tolerance(2))
+ aStatus = IntWalk_ArretSurPoint;
+ else
+ aStatus = IntWalk_PasTropGrand;
+ return aStatus;
+ }
+ Cosi = Du * sp.Direction2d().X() + Dv * sp.Direction2d().Y();
+ Cosi2 = Cosi * Cosi / Duv;
+ if (Cosi2 < CosRef2D || sp.Direction2d() * previousd2d < 0)
+ {
+ //angle 2d too great or change the side
+ Step = Step / 2.;
+ Standard_Real StepU = Abs(Step * previousd2d.X()), StepV = Abs(Step * previousd2d.Y());
+ if (StepU < tolerance(1) && StepV < tolerance(2))
+ aStatus = IntWalk_ArretSurPointPrecedent;
+ else
+ aStatus = IntWalk_PasTropGrand;
+ return aStatus;
+ }
+ }
+
+ if (!Finished)
+ {
+ if (aStatus == IntWalk_PointConfondu)
+ {
+ Standard_Real StepU = Min(Abs(1.5 * Du), pas * (UM - Um)), StepV = Min(Abs(1.5 * Dv), pas * (VM - Vm));
+
+ Standard_Real d2dx = Abs(previousd2d.X());
+ Standard_Real d2dy = Abs(previousd2d.Y());
+
+ if (d2dx < tolerance(1))
+ {
+ Step = StepV / d2dy;
+ }
+ else if (d2dy < tolerance(2))
+ {
+ Step = StepU / d2dx;
+ }
+ else
+ {
+ Step = Min(StepU / d2dx, StepV / d2dy);
+ }
+ }
+ else
+ {
+ // estimate the current vector.
+ // if vector/2<=current vector<= vector it is considered that the criterion
+ // is observed.
+ // otherwise adjust the step depending on the previous step
+
+ /*
+ Standard_Real Dist = Sqrt(Norme)/3.;
+ TColgp_Array1OfPnt Poles(1,4);
+ gp_Pnt POnCurv,Milieu;
+ Poles(1) = previousPoint.Value();
+ Poles(4) = sp.Point();
+ Poles(2) = Poles(1).XYZ() +
+ StepSign * Dist* previousd3d.Normalized().XYZ();
+ Poles(3) = Poles(4).XYZ() -
+ StepSign * Dist*sp.Direction3d().Normalized().XYZ();
+ BzCLib::PntPole(0.5,Poles,POnCurv);
+ Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
+ // FlecheCourante = Milieu.Distance(POnCurv);
+ Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
+ */
+
+ // Direct calculation :
+ // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
+ // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
+ // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
+ // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
+ // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
+ // the norm (square) of 3.*lambda (d1 - d4)/8.
+ // either the norm of :
+ // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
+ // which produces, taking the square :
+ // Norme * (d1-d4).SquareMagnitude()/64.
+
+ Standard_Real FlecheCourante = (previousd3d.Normalized().XYZ() - sp.Direction3d().Normalized().XYZ()).SquareModulus()
+ * Norme / 64.;
+
+ // if (FlecheCourante <= 0.5*fleche) {
+ if (FlecheCourante <= 0.25 * fleche * fleche)
+ {
+ Standard_Real d2dx = Abs(sp.Direction2d().X());
+ Standard_Real d2dy = Abs(sp.Direction2d().Y());
+
+ Standard_Real StepU = Min(Abs(1.5 * Du), pas * (UM - Um)), StepV = Min(Abs(1.5 * Dv), pas * (VM - Vm));
+
+ if (d2dx < tolerance(1))
+ {
+ Step = StepV / d2dy;
+ }
+ else if (d2dy < tolerance(2))
+ {
+ Step = StepU / d2dx;
+ }
+ else
+ {
+ Step = Min(StepU / d2dx, StepV / d2dy);
+ }
+ }
+ else
+ {
+ //if (FlecheCourante > fleche) { // step too great
+ if (FlecheCourante > fleche * fleche)
+ { // step too great
+ Step = Step / 2.;
+ Standard_Real StepU = Abs(Step * previousd2d.X()), StepV = Abs(Step * previousd2d.Y());
+
+ if (StepU < tolerance(1) && StepV < tolerance(2))
+ aStatus = IntWalk_ArretSurPointPrecedent;
+ else
+ aStatus = IntWalk_PasTropGrand;
+ }
+ else
+ {
+ Standard_Real d2dx = Abs(sp.Direction2d().X());
+ Standard_Real d2dy = Abs(sp.Direction2d().Y());
+
+ Standard_Real StepU = Min(Abs(1.5 * Du), pas * (UM - Um)), StepV = Min(Abs(1.5 * Dv), pas * (VM - Vm));
+
+ if (d2dx < tolerance(1))
+ {
+ Step = Min(Step, StepV / d2dy);
+ }
+ else if (d2dy < tolerance(2))
+ {
+ Step = Min(Step, StepU / d2dx);
+ }
+ else
+ {
+ Step = Min(Step, Min(StepU / d2dx, StepV / d2dy));
+ }
+ }
+ }
+ }
+ }
+ return aStatus;
+}
+
+//-- IntWalk_IWalking_6.gxx
+
+#ifndef OCCT_DEBUG
+ #define No_Standard_RangeError
+ #define No_Standard_OutOfRange
+#endif
+
+void IntWalk_IWalking::AddPointInCurrentLine(const Standard_Integer N,
+ const ThePointOfPath& PathPnt,
+ const Handle(IntWalk_TheIWLine)& CurrentLine) const
+{
+ IntSurf_PntOn2S Psol;
+ Psol.SetValue(ThePointOfPathTool::Value3d(PathPnt), reversed, wd1[N].ustart, wd1[N].vstart);
+ CurrentLine->AddPoint(Psol);
+}
+
+void IntWalk_IWalking::MakeWalkingPoint(const Standard_Integer Case,
+ const Standard_Real U,
+ const Standard_Real V,
+ TheIWFunction& sp,
+ IntSurf_PntOn2S& Psol)
+
+{
+ // Case == 1 : make a WalkinkPoint.
+ // Case == 2 : make a WalkinkPoint.
+ // The computation of the tangency on is done
+ // Case == 10 + i : make a WalkinkPoint according to i.
+ // but F is updated according to U and V
+ // Case == other : the exception Standard_Failure is raised.
+
+ if ((Case == 1) || (Case == 2))
+ {
+ Psol.SetValue(sp.Point(), reversed, U, V);
+ }
+ else if (Case == 11 || Case == 12)
+ {
+ Standard_Real aUV[2] = {}, aFF[1] = {}, aDD[1][2] = {};
+ math_Vector UV(aUV, 1, 2);
+ math_Vector FF(aFF, 1, 1);
+ math_Matrix DD(aDD, 1, 1, 1, 2);
+ UV(1) = U;
+ UV(2) = V;
+ sp.Values(UV, FF, DD);
+ MakeWalkingPoint(Case - 10, U, V, sp, Psol);
+ }
+ else
+ {
+ throw Standard_ConstructionError();
+ }
+}
+
+void IntWalk_IWalking::OpenLine(const Standard_Integer N,
+ const IntSurf_PntOn2S& Psol,
+ const ThePOPIterator& Pnts1,
+ TheIWFunction& sp,
+ const Handle(IntWalk_TheIWLine)& Line)
+// **************** open the line and restart in the other direction********
+
+{
+ ThePointOfPath PathPnt;
+
+ Standard_Real aUV[2], aFF[1], aDD[1][2];
+ math_Vector UV(aUV, 1, 2);
+ math_Vector FF(aFF, 1, 1);
+ math_Matrix DD(aDD, 1, 1, 1, 2);
+
+ previousPoint = Line->Value(1);
+ if (!reversed)
+ {
+ previousPoint.ParametersOnS2(UV(1), UV(2));
+ }
+ else
+ {
+ previousPoint.ParametersOnS1(UV(1), UV(2));
+ }
+ sp.Values(UV, FF, DD);
+ previousd3d = sp.Direction3d();
+ previousd2d = sp.Direction2d();
+
+ if (N > 0)
+ { //departure point given at input
+ PathPnt = Pnts1.Value(N);
+ //mark the line as open with a given stop point
+ Line->AddStatusFirst(Standard_False, Standard_True, N, PathPnt);
+
+ AddPointInCurrentLine(N, PathPnt, Line);
+ }
+ else
+ {
+ if (N < 0)
+ Line->AddPoint(Psol);
+ Line->AddStatusFirst(Standard_False, Standard_False);
+ //mark the line as open without given stop point
+ }
+ Line->Reverse(); //inverser la ligne
+ Line->SetTangentVector(previousd3d.Reversed(), Line->NbPoints());
+}
+
+Standard_Boolean IntWalk_IWalking::IsValidEndPoint(const Standard_Integer IndOfPoint, const Standard_Integer IndOfLine)
+{
+ if (PointLineLine.IsEmpty())
+ return Standard_True;
+
+ TColStd_ListIteratorOfListOfInteger itl(PointLineLine(IndOfPoint));
+ for (; itl.More(); itl.Next())
+ if (itl.Value() == IndOfLine)
+ {
+ PointLineLine(IndOfPoint).Remove(itl);
+ return Standard_True;
+ }
+ return Standard_False;
+}
+
+void IntWalk_IWalking::RemoveTwoEndPoints(const Standard_Integer IndOfPoint)
+{
+ if (PointLineLine.IsBound(IndOfPoint))
+ {
+ Standard_Integer Line1 = PointLineLine(IndOfPoint).First();
+ Standard_Integer Line2 = PointLineLine(IndOfPoint).Last();
+ for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
+ {
+ if (seqAlone(iseq) == Line1 || seqAlone(iseq) == Line2)
+ seqAlone.Remove(iseq--);
+ }
+ }
+}
+
+Standard_Boolean IntWalk_IWalking::IsPointOnLine(const gp_Pnt2d& theP2d, const Standard_Integer Irang)
+{
+ const Handle(IntWalk_TheIWLine)& aLine = lines.Value(Abs(Irang));
+ for (Standard_Integer i = 1; i <= aLine->NbPoints(); i++)
+ {
+ gp_Pnt2d P2d1 = aLine->Value(i).ValueOnSurface(reversed);
+ if (Abs(P2d1.X() - theP2d.X()) <= tolerance(1) && Abs(P2d1.Y() - theP2d.Y()) <= tolerance(2))
+ return Standard_True;
+ if (i < aLine->NbPoints())
+ {
+ gp_Pnt2d P2d2 = aLine->Value(i + 1).ValueOnSurface(reversed);
+ gp_Vec2d PP1(theP2d, P2d1);
+ gp_Vec2d PP2(theP2d, P2d2);
+ if (PP1 * PP2 < 0)
+ return Standard_True;
+ }
+ }
+ return Standard_False;
+}
+
+//==================================================================================
+//function : IsPointOnLine
+//purpose : Projects thePOn2S on the nearest segment of the already computed line.
+// The retrieved projection point (aPa) is refined using theSolver.
+// After the refinement, we will obtain a point aPb.
+// If thePOn2S is quite far from aPb then thePOn2S is not
+// in the line.
+// Every already computed line is checked.
+//==================================================================================
+Standard_Boolean IntWalk_IWalking::IsPointOnLine(const IntSurf_PntOn2S& thePOn2S,
+ const math_Vector& theInfBounds,
+ const math_Vector& theSupBounds,
+ math_FunctionSetRoot& theSolver,
+ TheIWFunction& theFunc)
+{
+ const Standard_Real eps = Epsilon(1.);
+ const gp_Pnt& aP3d = thePOn2S.Value();
+
+ for (Standard_Integer aLIdx = 1; aLIdx <= lines.Length(); aLIdx++)
+ {
+ const Handle(IntSurf_LineOn2S)& aL = lines(aLIdx)->Line();
+
+ if (aL->IsOutBox(aP3d))
+ continue;
+
+ //Look for the nearest segment
+ Standard_Real aUMin = 0.0, aVMin = 0.0;
+ Standard_Real aMinSqDist = RealLast();
+ for (Standard_Integer aPtIdx = 1; aPtIdx < aL->NbPoints(); aPtIdx++)
+ {
+ const gp_Pnt& aP1 = aL->Value(aPtIdx).Value();
+ const gp_Pnt& aP2 = aL->Value(aPtIdx + 1).Value();
+
+ const gp_XYZ aP1P(aP3d.XYZ() - aP1.XYZ());
+ const gp_XYZ aP1P2(aP2.XYZ() - aP1.XYZ());
+
+ const Standard_Real aSq12 = aP1P2.SquareModulus();
+
+ if (aSq12 < gp::Resolution())
+ continue;
+
+ const Standard_Real aDP = aP1P.Dot(aP1P2);
+
+ Standard_Real aSqD = RealLast();
+ if (aDP < 0.0)
+ {
+ continue;
+ }
+ else if (aDP > aSq12)
+ {
+ continue;
+ }
+ else
+ {
+ aSqD = aP1P.CrossSquareMagnitude(aP1P2) / aSq12;
+ }
+
+ if (aSqD < aMinSqDist)
+ {
+ aMinSqDist = aSqD;
+
+ const Standard_Real aL1 = aDP / aSq12;
+ const Standard_Real aL2 = 1.0 - aL1;
+
+ if (aL1 < eps || aL2 < eps)
+ {
+ return Standard_True;
+ }
+
+ Standard_Real aU1, aV1, aU2, aV2;
+ aL->Value(aPtIdx).ParametersOnSurface(reversed, aU1, aV1);
+ aL->Value(aPtIdx + 1).ParametersOnSurface(reversed, aU2, aV2);
+
+ aUMin = aL1 * aU2 + aL2 * aU1;
+ aVMin = aL1 * aV2 + aL2 * aV1;
+ }
+ }
+
+ if (aMinSqDist > Precision::Infinite())
+ continue;
+
+ math_Vector aVecPrms(1, 2);
+ aVecPrms(1) = aUMin;
+ aVecPrms(2) = aVMin;
+ theSolver.Perform(theFunc, aVecPrms, theInfBounds, theSupBounds);
+ if (!theSolver.IsDone())
+ continue;
+
+ theSolver.Root(aVecPrms);
+
+ const gp_Pnt aPa(theFunc.PSurface()->Value(aUMin, aVMin)), aPb(theFunc.PSurface()->Value(aVecPrms(1), aVecPrms(2)));
+ const Standard_Real aSqD1 = aPb.SquareDistance(aP3d);
+ const Standard_Real aSqD2 = aPa.SquareDistance(aPb);
+
+ if (aSqD1 < 4.0 * aSqD2)
+ {
+ return Standard_True;
+ }
+ }
-#include "../IntWalk/IntWalk_IWalking_1.gxx"
-#include "../IntWalk/IntWalk_IWalking_2.gxx"
-#include "../IntWalk/IntWalk_IWalking_3.gxx"
-#include "../IntWalk/IntWalk_IWalking_4.gxx"
-#include "../IntWalk/IntWalk_IWalking_5.gxx"
-#include "../IntWalk/IntWalk_IWalking_6.gxx"
+ return Standard_False;
+}
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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.
-
-#ifdef CHRONO
-#include <OSD_Chronometer.hxx>
-OSD_Chronometer Chronrsnld;
-
-#endif
-
-#include <NCollection_IncAllocator.hxx>
-#include <Precision.hxx>
-
-//==================================================================================
-// function : IsTangentExtCheck
-// purpose : Additional check if the point (theU, theV) in parametric surface
-// is a tangent point.
-// If that is TRUE then we can go along any (!) direction in order to
-// obtain next intersection point. At present, this case is difficult
-// for processing. Therefore, we will return an empty intersection line
-// in this case.
-//==================================================================================
-static Standard_Boolean IsTangentExtCheck(TheIWFunction& theFunc,
- const Standard_Real theU,
- const Standard_Real theV,
- const Standard_Real theStepU,
- const Standard_Real theStepV,
- const Standard_Real theUinf,
- const Standard_Real theUsup,
- const Standard_Real theVinf,
- const Standard_Real theVsup)
-{
- const Standard_Real aTol = theFunc.Tolerance();
- const Standard_Integer aNbItems = 4;
- const Standard_Real aParU[aNbItems] = { Min(theU + theStepU, theUsup),
- Max(theU - theStepU, theUinf),
- theU, theU};
- const Standard_Real aParV[aNbItems] = { theV, theV,
- Min(theV + theStepV, theVsup),
- Max(theV - theStepV, theVinf)};
-
- math_Vector aX(1, 2), aVal(1, 1);
-
- for(Standard_Integer i = 0; i < aNbItems; i++)
- {
- aX.Value(1) = aParU[i];
- aX.Value(2) = aParV[i];
-
- if(!theFunc.Value(aX, aVal))
- continue;
-
- if(Abs(theFunc.Root()) > aTol)
- return Standard_False;
- }
-
- return Standard_True;
-}
-
-
-
-IntWalk_IWalking::IntWalk_IWalking (const Standard_Real Epsilon,
- const Standard_Real Deflection,
- const Standard_Real Increment,
- const Standard_Boolean theToFillHoles) :
- done(Standard_False),
- fleche(Deflection),
- pas(Increment),
- tolerance(1,2),
- epsilon(Epsilon*Epsilon),
- reversed(Standard_False),
- wd1 (IntWalk_VectorOfWalkingData::allocator_type (new NCollection_IncAllocator)),
- wd2 (wd1.get_allocator()),
- nbMultiplicities (wd1.get_allocator()),
- Um(0.0),
- UM(0.0),
- Vm(0.0),
- VM(0.0),
- ToFillHoles(theToFillHoles)
-{
-}
-
-
-//=======================================================================
-//function : Reset
-//purpose : Clears NCollection_Vector-based containers and adds
-// dummy data to maintain start index of 1 and consistent with
-// previous TCollection_Sequence-based implementation and other
-// used TCollection-based containers
-//=======================================================================
-
-void IntWalk_IWalking::Clear()
-{
- wd1.clear();
- wd2.clear();
- IntWalk_WalkingData aDummy;
- aDummy.etat = -10;
- aDummy.ustart = aDummy.vstart = 0.;
- wd1.push_back (aDummy);
- wd2.push_back (aDummy);
- nbMultiplicities.clear();
- nbMultiplicities.push_back (-1);
-
- done = Standard_False;
- seqAjout.Clear();
- lines.Clear();
-}
-
-// ***************************************************************************
- // etat1=12 not tangent, not passes
- // etat1=11 tangent, not passes
- // etat1=2 not tangent, passes
- // etat1=1 tangent, passes
- // after a point is processed its state becomes negative.
-// ***************************************************************************
- // etat2=13 interior start point on closed line
- // etat2=12 interior start point on open line
- // (line initially closed -> la line s is open)
- // after a point is processed (or if it is passed over during
- // routing) its state becomes negative.
-// ****************************************************************************
-
-//
-// Perform with interior points
-//
-void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
- const ThePOLIterator& Pnts2,
- TheIWFunction& Func,
- const ThePSurface& Caro,
- const Standard_Boolean Reversed)
-
-{
- Standard_Integer I;
- Standard_Boolean Rajout = Standard_False;
- Standard_Integer nbPnts1 = Pnts1.Length();
- Standard_Integer nbPnts2 = Pnts2.Length();
- Standard_Real U,V;
-
- Clear();
- reversed = Reversed;
-
- Um = ThePSurfaceTool::FirstUParameter(Caro);
- Vm = ThePSurfaceTool::FirstVParameter(Caro);
- UM = ThePSurfaceTool::LastUParameter(Caro);
- VM = ThePSurfaceTool::LastVParameter(Caro);
-
- if (UM < Um) {
- Standard_Real utemp = UM;
- UM = Um;
- Um = utemp;
- }
- if (VM < Vm) {
- Standard_Real vtemp = VM;
- VM = Vm;
- Vm = vtemp;
- }
-
- const Standard_Real aStepU = pas*(UM-Um), aStepV = pas*(VM-Vm);
-
- // Loading of etat1 and etat2 as well as ustart and vstart.
-
- TColStd_SequenceOfReal Umult;
- TColStd_SequenceOfReal Vmult;
-
- Standard_Integer decal=0;
- wd1.reserve (nbPnts1+decal);
- nbMultiplicities.reserve (nbPnts1+decal);
- for (I=1;I <= nbPnts1+decal; I++) {
- const ThePointOfPath& PathPnt = Pnts1.Value(I-decal);
- IntWalk_WalkingData aWD1;
- aWD1.etat = 1;
- if (!ThePointOfPathTool::IsPassingPnt(PathPnt))
- aWD1.etat = 11;
- if (!ThePointOfPathTool::IsTangent(PathPnt))
- ++aWD1.etat;
-
- if(aWD1.etat==2) {
- aWD1.etat=11;
- }
-
- ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
- mySRangeU.Add(aWD1.ustart);
- mySRangeV.Add(aWD1.vstart);
-
- wd1.push_back (aWD1);
- Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
- nbMultiplicities.push_back(aNbMult);
-
- for (Standard_Integer J = 1; J <= aNbMult; J++) {
- ThePointOfPathTool::Parameters(PathPnt, J, U, V);
- Umult.Append(U);
- Vmult.Append(V);
- }
- }
-
- wd2.reserve (nbPnts2);
- for (I = 1; I <= nbPnts2; I++) {
- IntWalk_WalkingData aWD2;
- aWD2.etat = 1;
- const IntSurf_InteriorPoint& anIP = Pnts2.Value(I);
- ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
- mySRangeU.Add(aWD2.ustart);
- mySRangeV.Add(aWD2.vstart);
-
- if (!IsTangentExtCheck(Func, aWD2.ustart, aWD2.vstart, aStepU, aStepV, Um, UM, Vm, VM))
- aWD2.etat = 13;
-
- wd2.push_back (aWD2);
- }
-
- tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
- tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
-
- Func.Set(Caro);
-
- if (mySRangeU.Delta() > Max(tolerance(1), Precision::PConfusion()))
- {
- mySRangeU.Enlarge(mySRangeU.Delta());
- mySRangeU.Common(Bnd_Range(Um, UM));
- }
- else
- {
- mySRangeU = Bnd_Range(Um, UM);
- }
-
- if (mySRangeV.Delta() > Max(tolerance(2), Precision::PConfusion()))
- {
- mySRangeV.Enlarge(mySRangeV.Delta());
- mySRangeV.Common(Bnd_Range(Vm, VM));
- }
- else
- {
- mySRangeV = Bnd_Range(Vm, VM);
- }
-
- // calculation of all open lines
- if (nbPnts1 != 0)
- ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout);
-
- // calculation of all closed lines
- if (nbPnts2 != 0)
- ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Func,Rajout);
-
- if (ToFillHoles)
- {
- Standard_Integer MaxNbIter = 10, nb_iter = 0;
- while (seqAlone.Length() > 1 && nb_iter < MaxNbIter)
- {
- nb_iter++;
- IntSurf_SequenceOfInteriorPoint PntsInHoles;
- TColStd_SequenceOfInteger CopySeqAlone = seqAlone;
- FillPntsInHoles(Func, CopySeqAlone, PntsInHoles);
- wd2.clear();
- IntWalk_WalkingData aDummy;
- aDummy.etat = -10;
- aDummy.ustart = aDummy.vstart = 0.;
- wd2.push_back (aDummy);
- Standard_Integer nbHoles = PntsInHoles.Length();
- wd2.reserve(nbHoles);
- for (I = 1; I <= nbHoles; I++)
- {
- IntWalk_WalkingData aWD2;
- aWD2.etat = 13;
- const IntSurf_InteriorPoint& anIP = PntsInHoles.Value(I);
- ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
- wd2.push_back (aWD2);
- }
- ComputeCloseLine(Umult,Vmult,Pnts1,PntsInHoles,Func,Rajout);
- }
- }
-
- for (I = 1; I <= nbPnts1; I++) {
- if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
- }
- done = Standard_True;
-}
-
-
-
-//
-// Perform without interior point
-//
-
-void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
- TheIWFunction& Func,
- const ThePSurface& Caro,
- const Standard_Boolean Reversed)
-
-{
- Standard_Integer I;
- Standard_Boolean Rajout = Standard_False;
- Standard_Integer nbPnts1 = Pnts1.Length();
- Standard_Real U,V;
-
- reversed = Reversed;
-
-
- // Loading of etat1 as well as ustart1 and vstart1.
-
- TColStd_SequenceOfReal Umult;
- TColStd_SequenceOfReal Vmult;
-
- wd1.reserve (nbPnts1);
- for (I=1;I <= nbPnts1; I++) {
- const ThePointOfPath& PathPnt = Pnts1.Value(I);
- IntWalk_WalkingData aWD1;
- aWD1.etat = 1;
- if (!ThePointOfPathTool::IsPassingPnt(PathPnt)) aWD1.etat = 11;
- if (!ThePointOfPathTool::IsTangent(PathPnt)) ++aWD1.etat;
- ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
- wd1.push_back (aWD1);
- Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
- nbMultiplicities.push_back(aNbMult);
-
- for (Standard_Integer J = 1; J <= aNbMult; J++) {
- ThePointOfPathTool::Parameters(PathPnt, J, U, V);
- Umult.Append(U);
- Vmult.Append(V);
- }
- }
-
- tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
- tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
-
- Um = ThePSurfaceTool::FirstUParameter(Caro);
- Vm = ThePSurfaceTool::FirstVParameter(Caro);
- UM = ThePSurfaceTool::LastUParameter(Caro);
- VM = ThePSurfaceTool::LastVParameter(Caro);
-
- if (UM < Um) {
- Standard_Real utemp = UM;
- UM = Um;
- Um = utemp;
- }
- if (VM < Vm) {
- Standard_Real vtemp = VM;
- VM = Vm;
- Vm = vtemp;
- }
-
- Func.Set(Caro);
-
- // calcul de toutes les lignes ouvertes
- if (nbPnts1 != 0) ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout);
-
- for (I = 1; I <= nbPnts1; I++) {
- if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
- }
- done = Standard_True;
-}
-
-
-
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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.
-
-//-- IntWalk_IWalking_2.gxx
-
-#include <Bnd_Range.hxx>
-#include <TColStd_MapOfInteger.hxx>
-
-#ifndef OCCT_DEBUG
-#define No_Standard_RangeError
-#define No_Standard_OutOfRange
-#endif
-
-static void CutVectorByTolerances (gp_Vec2d& theVector,
- const math_Vector& theTolerance)
-{
- if (Abs(theVector.X()) < theTolerance(1))
- theVector.SetX (0.);
- if (Abs(theVector.Y()) < theTolerance(2))
- theVector.SetY (0.);
-}
-
-// _______________________________________________
-//
-// Location of point (u, v) in the natural domain of a surface AND update
-// of couple (u, v) for the calculation of the next point.
-//
-Standard_Boolean IntWalk_IWalking::Cadrage
- (math_Vector& BornInf,
- math_Vector& BornSup,
- math_Vector& UVap,
- Standard_Real& Step,
-// Standard_Real& StepV,
- const Standard_Integer StepSign) const
-
-// there are always :
-// BorInf(1) <= UVap(1) <= BornSup(1) et BorInf(2) <= UVap(2) <= BornSup(2)
-// 1) check if the process point is out of the natural domain of the surface.
-// 2) if yes the approximated point is located on border taking the best direction
-// the step and a limit blocating one of the parameters during the recent call of
-// FunctionSetRoot are modified;
-// 3) couple (u, v) is recomputed by approximation for the calculation of the next point.
-// 4) return Standard_True if location, Standard_False if no location.
-{
- Standard_Real Duvx = previousd2d.X();
- Standard_Real Duvy = previousd2d.Y();
-
- if (!reversed) {
- previousPoint.ParametersOnS2(UVap(1),UVap(2));
- }
- else {
- previousPoint.ParametersOnS1(UVap(1),UVap(2));
- }
-
- Standard_Real U1 = UVap(1) + Step * Duvx * StepSign;
- Standard_Real V1 = UVap(2) + Step * Duvy * StepSign;
-
-
- Standard_Boolean infu = (U1 <= BornInf(1)+Precision::PConfusion());
- Standard_Boolean supu = (U1 >= BornSup(1)-Precision::PConfusion());
- Standard_Boolean infv = (V1 <= BornInf(2)+Precision::PConfusion());
- Standard_Boolean supv = (V1 >= BornSup(2)-Precision::PConfusion());
-
- Standard_Real theStepU,theStepV;
-
- if (!infu && !supu && !infv && !supv) {
- UVap(1) = U1;
- UVap(2) = V1;
- return Standard_False;
- }
-
- if ((infu || supu) && (infv || supv)) {
- if (infu) { // jag 940616
- if(Duvx) {
- theStepU = Abs((BornInf(1) - UVap(1)) / Duvx); // iso U =BornInf(1)
- }
- else {
- theStepU = Step;
- }
- }
- else {
- if(Duvx) {
- theStepU = Abs((BornSup(1) - UVap(1)) / Duvx); // iso U =BornSup(1)
- }
- else {
- theStepU = Step;
- }
- }
- if (infv) { // jag 940616
- if(Duvy) {
- theStepV = Abs((BornInf(2) - UVap(2)) / Duvy); // iso V =BornInf(2)
- }
- else {
- theStepV = Step;
- }
- }
- else {
- if(Duvy) {
- theStepV = Abs((BornSup(2) - UVap(2)) / Duvy); // iso V =BornSup(2)
- }
- else {
- theStepV = Step;
- }
- }
-
-
- if (theStepU <= theStepV) {
- Step = theStepU;
- if (infu) {
- UVap(1) = BornInf(1);
- BornSup(1) = BornInf(1);
- }
- else {
- UVap(1) = BornSup(1);
- BornInf(1) = BornSup(1);
- }
- UVap(2) += Step*Duvy*StepSign;
- }
- else {
- Step = theStepV;
- if (infv) {
- UVap(2) = BornInf(2);
- BornSup(2) = BornInf(2);
- }
- else {
- UVap(2) = BornSup(2);
- BornInf(2) = BornSup(2);
- }
- UVap(1) += Step*Duvx*StepSign;
- }
- return Standard_True;
- }
-
- else if (infu) { // jag 940616
- if(Duvx) {
- Standard_Real aStep = Abs((BornInf(1) - UVap(1)) / Duvx); // iso U =BornInf(1)
- if(aStep<Step) Step=aStep;
- }
- BornSup(1) = BornInf(1); // limit the parameter
- UVap(1) = BornInf(1);
- UVap(2) += Step*Duvy*StepSign;
- return Standard_True;
- }
- else if (supu) { // jag 940616
- if(Duvx) {
- Standard_Real aStep = Abs((BornSup(1) - UVap(1)) / Duvx); // iso U =BornSup(1)
- if(aStep<Step) Step=aStep;
- }
- BornInf(1) = BornSup(1); // limit the parameter
- UVap(1) = BornSup(1);
- UVap(2) += Step*Duvy*StepSign;
- return Standard_True;
- }
- else if (infv) { // jag 940616
- if(Duvy) {
- Standard_Real aStep = Abs((BornInf(2) - UVap(2)) / Duvy); // iso V =BornInf(2)
- if(aStep<Step) Step=aStep;
- }
- BornSup(2) = BornInf(2);
- UVap(1) += Step*Duvx*StepSign;
- UVap(2) = BornInf(2);
- return Standard_True;
- }
- else if (supv) { // jag 940616
- if(Duvy) {
- Standard_Real aStep = Abs((BornSup(2) - UVap(2)) / Duvy); // iso V =BornSup(2)
- if(aStep<Step) Step=aStep;
- }
- BornInf(2) = BornSup(2);
- UVap(1) += Step*Duvx*StepSign;
- UVap(2) = BornSup(2);
- return Standard_True;
- }
- return Standard_True;
-}
-
-
-Standard_Boolean IntWalk_IWalking::TestArretPassage
- (const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- TheIWFunction& sp,
- math_Vector& UV,
- Standard_Integer& Irang)
-
-// Umult et Vmult : table of stop (or crossing) points on border,
-// here only the crossing points are taken into account.
-// UV : the current point.
-// Irang : at exit : give index of the stop point in uvstart1 or 0.
-// consider that there is no risk of crossing only if there is one crossing point.
-
-
-// test of stop for an OPEN intersection line
-// 1) crossing test on all interior points
-// 2) stop test on all start points
-// if a stop is detected, the index of the stop point (Irang) is returned
-// in the iterator of start points and the associated parameters in UV space.
-{
- Standard_Real Up, Vp, Du, Dv, Dup, Dvp, Utest,Vtest;
- Standard_Integer j, N, ind;
- Standard_Real tolu = tolerance(1);
- Standard_Real tolv = tolerance(2);
- Standard_Real tolu2 = 10.*tolerance(1);
- Standard_Real tolv2 = 10.*tolerance(2);
-
- Standard_Boolean Arrive = Standard_False;
-
- // crossing test on point that can start a loop; mark
- // as processed if passes through an open line
-
- if (!reversed) {
- previousPoint.ParametersOnS2(Up,Vp);
- }
- else {
- previousPoint.ParametersOnS1(Up,Vp);
- }
-
- for (size_t i = 1; i < wd2.size(); i++) {
- if (wd2[i].etat > 0) {
- // debug jag 05.04.94
-
-// if ((Up-wd2[i].ustart)*(UV(1)-wd2[i].ustart) +
-// (Vp-wd2[i].vstart)*(UV(2)-wd2[i].vstart) <= 0)
- Utest = wd2[i].ustart;
- Vtest = wd2[i].vstart;
-
- Du = UV(1)-Utest;
- Dv = UV(2)-Vtest;
- Dup = Up - Utest;
- Dvp = Vp - Vtest;
-
-//-- lbr le 30 oct 97
-
- //IFV for OCC20285
-
- if ((Abs(Du) < tolu2 && Abs(Dv) < tolv2) ||
- (Abs(Dup) < tolu2 && Abs(Dvp) < tolv2)) {
-
- wd2[i].etat = -wd2[i].etat;
- }
- else {
- Standard_Real DDu = (UV(1)-Up);
- Standard_Real DDv = (UV(2)-Vp);
- Standard_Real DDD = DDu*DDu+DDv*DDv;
- Standard_Real DD1 = Du*Du+Dv*Dv;
- if(DD1<=DDD) {
- Standard_Real DD2 = Dup*Dup+Dvp*Dvp;
- if(DD2<=DDD && ((Du*Dup) + (Dv*Dvp*tolu/tolv) <= 0.)) {
- wd2[i].etat = -wd2[i].etat;
- }
- }
- }
- }
- }
-
- // stop test on point given at input and not yet processed
-
-// Modified by Sergey KHROMOV - Tue Nov 20 10:55:01 2001 Begin
-// Check of all path points in the following order:
-// * First check all not treated points;
-// * After that check of already treated ones.
- Standard_Integer l;
-
- //// Modified by jgv, 28.07.2010 for OCC21914 ////
- // There are several path points between (Up,Vp) and UV
- // So several path points satisfy the condition
- // Dup*UV1mUtest + Dvp*UV2mVtest) < 0
- // We choose from them the path point with
- // minimum distance to (Up,Vp)
- TColStd_SequenceOfInteger i_candidates;
- TColStd_SequenceOfReal SqDist_candidates;
-
- for (l = 1; l <= 2 && !Arrive; l++) {
- Standard_Boolean isToCheck;
-
- for (size_t i = 1; i < wd1.size(); i++) {
- if (l == 1)
- isToCheck = (wd1[i].etat > 0);
- else
- isToCheck = (wd1[i].etat < 0);
-
- if (isToCheck) {
-// Modified by Sergey KHROMOV - Tue Nov 20 11:03:16 2001 End
-
- // debug jag voir avec isg
-
- Utest = wd1[i].ustart;
- Vtest = wd1[i].vstart;
- Dup = Up - Utest;
- Dvp = Vp - Vtest;
- if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv) {
- Standard_Real UV1mUtest = UV(1)-Utest;
- Standard_Real UV2mVtest = UV(2)-Vtest;
- if(( (Dup*UV1mUtest + Dvp*UV2mVtest) < 0) ||
- ( Abs(UV1mUtest) < tolu
- && Abs(UV2mVtest) < tolv)) {
- i_candidates.Append((Standard_Integer)i);
- SqDist_candidates.Append(Dup*Dup + Dvp*Dvp);
- /*
- Irang=i;
- Arrive = Standard_True;
- UV(1) = Utest;
- UV(2) = Vtest;
- */
- }
- else if (nbMultiplicities[i] > 0 && i_candidates.IsEmpty()) {
- N=0;
- for (size_t k = 1; k < i; k++) {
- N+=nbMultiplicities[k];
- }
- for (j = N + 1; j <= N + nbMultiplicities[i]; j++) {
- if (((Up-Umult(j))*(UV(1)-Umult(j)) +
- (Vp-Vmult(j))*(UV(2)-Vmult(j)) < 0) ||
- (Abs(UV(1)-Umult(j)) < tolu &&
- Abs(UV(2)-Vmult(j)) < tolv)) {
- Irang=(Standard_Integer)i;
- Arrive = Standard_True;
- UV(1) = Utest;
- UV(2) = Vtest;
- break;
- }
- }
- }
- if (Arrive) {
- Standard_Real abidF[1], abidD[1][2];
- math_Vector bidF(abidF,1,1);
- math_Matrix bidD(abidD,1,1,1,2);
- sp.Values(UV,bidF,bidD);
- break;
- }
- }
- }
- } //end of for (i = 1; i < wd1.size(); i++)
- if (!i_candidates.IsEmpty())
- {
- Standard_Real MinSqDist = RealLast();
- for (ind = 1; ind <= i_candidates.Length(); ind++)
- if (SqDist_candidates(ind) < MinSqDist)
- {
- MinSqDist = SqDist_candidates(ind);
- Irang = i_candidates(ind);
- }
- Arrive = Standard_True;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- }
- } //end of for (l = 1; l <= 2 && !Arrive; l++)
- return Arrive;
-}
-
-Standard_Boolean IntWalk_IWalking::TestArretPassage
- (const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const math_Vector& UV,
- const Standard_Integer Index,
- Standard_Integer& Irang)
-{
-// Umult, Vmult : table of stop (or crossing) points on border, here
-// only crossing points are taken into account.
-// UV : the current point.
-// Index : index of the start point in uvstart2 of the current line
-// (this is an interior point).
-// Irang : at output : gives the index of the point passing in uvstart1 or 0.
-// consider that there is risk to cross only one crossing point.
-
-// test of stop for a CLOSED intersection line.
-// 1) test of crossing on all interior points.
-// 2) test of crossing on all crossing points.
-
- Standard_Real Up, Vp, Scal;
- Standard_Boolean Arrive = Standard_False;
- Standard_Integer N, k, i;
- Standard_Real Utest,Vtest;
- Standard_Real tolu = tolerance(1);
- Standard_Real tolv = tolerance(2);
-
-
- // tests of stop and of crossing on all interior points.
-
- if (!reversed) {
- previousPoint.ParametersOnS2(Up,Vp);
- }
- else {
- previousPoint.ParametersOnS1(Up,Vp);
- }
-
- Standard_Real UV1=UV(1);
- Standard_Real UV2=UV(2);
-
-
- //Normalizing factor. If it is less than 1.0 then the range will be expanded.
- //This is no good for computation. Therefore, it is limited.
- //Do not limit this factor in case of highly anisotropic parametrization
- //(parametric space is considerably larger in one direction than another).
- const Standard_Boolean isHighlyAnisotropic = Max(tolu, tolv) > 1000. * Min(tolu, tolv);
- const Standard_Real deltau = mySRangeU.IsVoid() ? UM - Um
- : (isHighlyAnisotropic ? mySRangeU.Delta()
- : Max(mySRangeU.Delta(), 1.0));
- const Standard_Real deltav = mySRangeV.IsVoid() ? VM - Vm
- : (isHighlyAnisotropic ? mySRangeV.Delta()
- : Max(mySRangeV.Delta(), 1.0));
-
- Up/=deltau; UV1/=deltau;
- Vp/=deltav; UV2/=deltav;
-
- tolu/=deltau;
- tolv/=deltav;
-
- Standard_Real tolu2=tolu+tolu;
- Standard_Real tolv2=tolv+tolv;
-
-
- Standard_Real dPreviousCurrent = (Up-UV1)*(Up-UV1)+(Vp-UV2)*(Vp-UV2);
- for (k = 1; k < (int)wd2.size(); k++) {
- if (wd2[k].etat > 0) {
- Utest = wd2[k].ustart;
- Vtest = wd2[k].vstart;
-
- Utest/=deltau;
- Vtest/=deltav;
-
- Standard_Real UV1mUtest=UV1-Utest;
- Standard_Real UV2mVtest=UV2-Vtest;
- if( (UV1mUtest<tolu2 && UV1mUtest>-tolu2)
- && (UV2mVtest<tolv2 && UV2mVtest>-tolv2)) {
- if(Index!=k) {
- //-- cout<<"* etat2 : ("<<k<<")"<<endl;
- wd2[k].etat=-wd2[k].etat; //-- mark the point as a crossing point
- }
- else { //-- Index == k
- //-- cout<<"* Arrive"<<endl;
- Arrive=Standard_True;
- }
- }
- else {
- Standard_Real UpmUtest = (Up-Utest);
- Standard_Real VpmVtest = (Vp-Vtest);
- Standard_Real dPreviousStart = (UpmUtest)*(UpmUtest)+(VpmVtest)*(VpmVtest);
- Standard_Real dCurrentStart = UV1mUtest * UV1mUtest + UV2mVtest * UV2mVtest;
-
- Scal=(UpmUtest)*(UV1mUtest)+(VpmVtest)*(UV2mVtest);
- if( (Abs(UpmUtest)<tolu && Abs(VpmVtest)<tolv)) {
- if(Index != k ) {
- //-- cout<<"** etat2 : ("<<k<<")"<<endl;
- wd2[k].etat = -wd2[k].etat;
- }
- }
- else if(Scal<0 && (dPreviousStart+dCurrentStart < dPreviousCurrent)) {
- if (Index == k ) { // on a boucle.
- Arrive = Standard_True;
- //-- cout<<"** Arrive : k="<<k<<endl;
- }
- else {
- //-- cout<<"*** etat2 : ("<<k<<")"<<endl;
- wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
- }
- }
- else if(k!=Index) {
- if(dPreviousStart < dPreviousCurrent*0.25) {
- wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
- //-- cout<<"**** etat2 : ("<<k<<")"<<endl;
- }
- else {
- if(dCurrentStart < dPreviousCurrent*0.25) {
- //-- cout<<"***** etat2 : ("<<k<<")"<<endl;
- wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
- }
- else {
- Standard_Real UMidUtest = 0.5*(UV1+Up)-Utest;
- Standard_Real VMidVtest = 0.5*(UV2+Vp)-Vtest;
- Standard_Real dMiddleStart = UMidUtest* UMidUtest+VMidVtest*VMidVtest;
-
- if(dMiddleStart < dPreviousCurrent*0.5) {
- //-- cout<<"*********** etat2 : ("<<k<<")"<<endl;
- wd2[k].etat = -wd2[k].etat; // mark the point as a crossing point
- }
- }
- }
- }
- }
- }
- }
-
- // crossing test on crossing points.
-
- Irang =0;
- for (i = 1; i < (int)wd1.size(); i++) {
- if (wd1[i].etat > 0 && wd1[i].etat < 11) { //test of crossing points
- Utest = wd1[i].ustart;
- Vtest = wd1[i].vstart;
- Utest/=deltau;
- Vtest/=deltav;
-
- if (((Up-Utest) * (UV1-Utest) + (Vp-Vtest) * (UV2-Vtest) < 0) ||
- (Abs(UV1-Utest) < tolu && Abs(UV2-Vtest) < tolv))
- Irang = i;
- else if (nbMultiplicities[i] > 0) {
- N=0;
- for (k = 1; k < i; k++) N = N + nbMultiplicities[k];
- for (Standard_Integer j = N + 1; j <= N + nbMultiplicities[i]; j++) {
- Standard_Real Umultj = Umult(j)/deltau;
- Standard_Real Vmultj = Vmult(j)/deltav;
- if (((Up-Umultj)*(UV1-Umultj) +
- (Vp-Vmultj)*(UV2-Vmultj) < 0) ||
- (Abs(UV1-Umultj) < tolu &&
- Abs(UV2-Vmultj) < tolv)) {
- Irang=i;
- break;
- }
- }
- }
- }
- }
- return Arrive;
-}
-
-
-Standard_Boolean IntWalk_IWalking::TestArretAjout
- (TheIWFunction& sp,
- math_Vector& UV,
- Standard_Integer& Irang,
- IntSurf_PntOn2S& Psol)
-
-// test of stop on added points
-// these are the points on the natural biorder that were not given at input
-// return : Psol, the added point.
-// Irang, index in the iterator of added points.
-// UV, parameter of the added point.
-//
-{
- Standard_Boolean Arrive = Standard_False;
- Standard_Real U1,V1;
- Standard_Real Up,Vp;
-
- if (!reversed) {
- previousPoint.ParametersOnS2(Up,Vp);
- }
- else {
- previousPoint.ParametersOnS1(Up,Vp);
- }
-
- Standard_Integer nbAjout = seqAjout.Length();
- for (Standard_Integer i = 1; i <= nbAjout; i++) {
- Irang = seqAjout.Value(i);
-
-// add test Abs(Irang) <= lines.Length() for the case when
-// a closed line is opened by adding a 1 point on this same
-// line. Anyway there is a huge problem as 2 points will be
-// added on this line...
-
- if (Abs(Irang) <= lines.Length()) {
-
- const Handle(IntWalk_TheIWLine)& Line = lines.Value(Abs(Irang));
- if (Irang>0)
- Psol = Line->Value(Line->NbPoints());
- else
- Psol = Line->Value(1);
- if (!reversed) {
- Psol.ParametersOnS2(U1, V1);
- }
- else {
- Psol.ParametersOnS1(U1, V1);
- }
- if (((Up-U1) * (UV(1)-U1) +
- (Vp-V1) * (UV(2)-V1)) < 0 ||
- (Abs(UV(1)-U1) < tolerance(1) &&
- Abs(UV(2)-V1) < tolerance(2))) {
-//jag 940615 Irang= -Abs(Irang);
- Arrive = Standard_True;
- UV(1) = U1;
- UV(2) = V1;
- Standard_Real abidF[1], abidD[1][2];
- math_Vector bidF(abidF,1,1);
- math_Matrix bidD(abidD,1,1,1,2);
- sp.Values(UV,bidF,bidD);
- break;
- }
- }
- }
- return Arrive;
-}
-
-void IntWalk_IWalking::FillPntsInHoles(TheIWFunction& sp,
- TColStd_SequenceOfInteger& CopySeqAlone,
- IntSurf_SequenceOfInteriorPoint& PntsInHoles)
-{
- math_Vector BornInf(1,2), BornSup(1,2);
- BornInf(1) = Um;
- BornSup(1) = UM;
- BornInf(2) = Vm;
- BornSup(2) = VM;
- PointLineLine.Clear();
- TColStd_SequenceOfInteger SeqToRemove;
- TColStd_MapOfInteger BadSolutions;
-
- for (Standard_Integer i = 1; i < CopySeqAlone.Length(); i++)
- {
- Standard_Integer Irang1 = CopySeqAlone(i);
- if (Irang1 == 0)
- continue;
- Standard_Boolean ToRemove = Standard_False;
- IntSurf_PntOn2S PointAlone1, PointAlone2;
- const Handle(IntWalk_TheIWLine)& Line1 = lines.Value(Abs(Irang1));
- if (Irang1 > 0)
- PointAlone1 = Line1->Value(Line1->NbPoints());
- else
- PointAlone1 = Line1->Value(1);
- gp_Pnt2d P2d1 = PointAlone1.ValueOnSurface(reversed), P2d2;
- Standard_Real MinSqDist = RealLast();
- Standard_Integer MinRang = 0, MinIndex = 0;
- for (Standard_Integer j = i+1; j <= CopySeqAlone.Length(); j++)
- {
- Standard_Integer Irang2 = CopySeqAlone(j);
- if (Irang2 == 0 ||
- BadSolutions.Contains(Irang2))
- continue;
- const Handle(IntWalk_TheIWLine)& Line2 = lines.Value(Abs(Irang2));
- if (Irang2 > 0)
- PointAlone2 = Line2->Value(Line2->NbPoints());
- else
- PointAlone2 = Line2->Value(1);
- P2d2 = PointAlone2.ValueOnSurface(reversed);
- Standard_Real aSqDist = P2d1.SquareDistance(P2d2);
- if (aSqDist < MinSqDist)
- {
- MinSqDist = aSqDist;
- MinRang = Irang2;
- MinIndex = j;
- }
- }
- //processing points from Irang1 and MinRang
- if (MinRang == 0)
- {
- SeqToRemove.Append(Irang1);
- BadSolutions.Clear();
- continue;
- }
- //Ends of same line
- if (Abs(Irang1) == Abs(MinRang) &&
- lines.Value(Abs(Irang1))->NbPoints() == 2)
- {
- SeqToRemove.Append(Irang1);
- SeqToRemove.Append(MinRang);
- CopySeqAlone(i) = 0;
- CopySeqAlone(MinIndex) = 0;
- BadSolutions.Clear();
- continue;
- }
- ///////////////////
- const Handle(IntWalk_TheIWLine)& Line2 = lines.Value(Abs(MinRang));
- if (MinRang > 0)
- PointAlone2 = Line2->Value(Line2->NbPoints());
- else
- PointAlone2 = Line2->Value(1);
- gp_Pnt Pnt1 = PointAlone1.Value();
- gp_Pnt Pnt2 = PointAlone2.Value();
- P2d2 = PointAlone2.ValueOnSurface(reversed);
- Standard_Real MinSqDist3d = Pnt1.SquareDistance(Pnt2);
- if (MinSqDist3d <= epsilon ||
- (Abs(P2d1.X() - P2d2.X()) <= tolerance(1) &&
- Abs(P2d1.Y() - P2d2.Y()) <= tolerance(2))) //close points
- ToRemove = Standard_True;
- else //real curve
- {
- math_Vector UVap(1,2), UV(1,2);
- UVap(1) = (P2d1.X() + P2d2.X())/2;
- UVap(2) = (P2d1.Y() + P2d2.Y())/2;
- math_FunctionSetRoot Rsnld(sp, tolerance);
- Rsnld.Perform(sp, UVap, BornInf, BornSup);
- if (Rsnld.IsDone() &&
- Abs(sp.Root()) <= sp.Tolerance() &&
- !sp.IsTangent())
- {
- Rsnld.Root(UV);
- gp_Pnt2d Pmid(UV(1),UV(2));
- gp_Vec2d P1P2(P2d1, P2d2);
- gp_Vec2d P1Pmid(P2d1, Pmid);
- gp_Vec2d P2Pmid(P2d2, Pmid);
- Standard_Real ScalProd1 = P1P2 * P1Pmid;
- Standard_Real ScalProd2 = P1P2 * P2Pmid;
- Standard_Boolean IsPmidValid = (ScalProd1 > 0. && ScalProd2 < 0); //Pmid is in the middle
- if (IsPmidValid)
- {
- for (Standard_Integer iline = 1; iline <= lines.Length(); iline++)
- if (IsPointOnLine(Pmid,iline))
- {
- IsPmidValid = Standard_False;
- break;
- }
- }
- if (IsPmidValid)
- {
- IntSurf_InteriorPoint aPoint(sp.Point(), UV(1), UV(2),
- sp.Direction3d(),
- sp.Direction2d());
- PntsInHoles.Append(aPoint);
- TColStd_ListOfInteger LineLine;
- LineLine.Append(Irang1);
- LineLine.Append(MinRang);
- PointLineLine.Bind(PntsInHoles.Length(), LineLine);
- }
- else
- {
- BadSolutions.Add(MinRang);
- i--;
- continue;
- }
- }
- else
- {
- BadSolutions.Add(MinRang);
- i--;
- continue;
- }
- }
- CopySeqAlone(i) = 0;
- CopySeqAlone(MinIndex) = 0;
- if (ToRemove)
- {
- SeqToRemove.Append(Irang1);
- SeqToRemove.Append(MinRang);
- }
- BadSolutions.Clear();
- }
-
- for (Standard_Integer i = 1; i <= SeqToRemove.Length(); i++)
- for (Standard_Integer j = 1; j <= seqAlone.Length(); j++)
- if (seqAlone(j) == SeqToRemove(i))
- {
- seqAlone.Remove(j);
- break;
- }
-}
-
-void IntWalk_IWalking::TestArretCadre
- (const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const Handle(IntWalk_TheIWLine)& Line,
- TheIWFunction& sp,
- math_Vector& UV,
- Standard_Integer& Irang)
-
-// test of stop when located on border.
-// tried all tests of stop and arrived.
-// test of stop on all given departure points already marked and on the entire current line.
-// This line can be shortened if the stop point is found.
-// Abs(Irang) = index in the iterator of departure points or 0
-// if Irang <0 , it is necessary to add this point on the line (no Line->Cut)
-// UV = parameter of the departure point
-{
- Standard_Real Scal, Up, Vp, Uc, Vc;
- Standard_Integer N;
- Standard_Boolean Found = Standard_False;
-
-
- Irang =0;
- for (Standard_Integer i = 1; i < (int)wd1.size(); i++) {
- if (wd1[i].etat < 0) {
- N=0; // range in UVMult.
- if (nbMultiplicities[i] > 0) {
- for (Standard_Integer k = 1; k < i; k++)
- N+=nbMultiplicities[k];
- }
- if (!reversed) {
- Line->Value(1).ParametersOnS2(Up,Vp);
- }
- else {
- Line->Value(1).ParametersOnS1(Up,Vp);
- }
- Standard_Integer nbp= Line->NbPoints();
- for (Standard_Integer j = 2; j <= nbp; j++) {
- if (!reversed) {
- Line->Value(j).ParametersOnS2(Uc,Vc);
- }
- else {
- Line->Value(j).ParametersOnS1(Uc,Vc);
- }
-
- gp_Vec2d aVec1 (Up-wd1[i].ustart, Vp-wd1[i].vstart),
- aVec2 (Uc-wd1[i].ustart, Vc-wd1[i].vstart);
- CutVectorByTolerances (aVec1, tolerance);
- CutVectorByTolerances (aVec2, tolerance);
-
- Scal = aVec1 * aVec2;
-
- // if a stop point is found: stop the line on this point.
- if (Scal < 0) {
- Line->Cut(j); nbp= Line->NbPoints();
- Irang = i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- }
- else if (Abs(Uc-wd1[i].ustart) < tolerance(1) &&
- Abs(Vc-wd1[i].vstart) < tolerance(2) ) {
- Line->Cut(j); nbp= Line->NbPoints();
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- }
- else if (nbMultiplicities[i] > 0) {
- for (Standard_Integer k = N+1; k <= N + nbMultiplicities[i]; k++) {
-
- aVec1.SetCoord (Up-Umult(k), Vp-Vmult(k)),
- aVec2.SetCoord (Uc-Umult(k), Vc-Vmult(k));
- CutVectorByTolerances (aVec1, tolerance);
- CutVectorByTolerances (aVec2, tolerance);
-
- Scal = aVec1 * aVec2;
-
- if (Scal < 0) {
- Line->Cut(j); nbp= Line->NbPoints();
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- break;
- }
- else if (Abs(Uc-Umult(k)) < tolerance(1) &&
- Abs(Vc-Vmult(k)) < tolerance(2)) {
- Line->Cut(j); nbp= Line->NbPoints();
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- break;
- }
- }
- }
- if (Found) {
- Standard_Real abidF[1], abidD[1][2];
- math_Vector bidF(abidF,1,1);
- math_Matrix bidD(abidD,1,1,1,2);
- sp.Values(UV,bidF,bidD);
- Standard_Integer NBP = Line->NbPoints();
- Standard_Integer Indextg;
- Line->TangentVector(Indextg);
- if(Indextg > NBP) {
- if(j>3 && j<=NBP+1) {
- gp_Vec Dir3d = sp.Direction3d();
- gp_Vec Dir3d1 = gp_Vec(Line->Value(j-2).Value(),Line->Value(j-1).Value());
- Standard_Real dot = Dir3d.Dot(Dir3d1);
- if(dot<0.0) { // Normally this Function should not be used often !!!
- Dir3d.Reverse();
- //-- cout<<" IntWalk_IWalking_2.gxx REVERSE "<<endl;
- }
- Line->SetTangentVector(previousd3d,j-1);
- }
-#ifdef OCCT_DEBUG
- else {
- std::cout<<" IntWalk_IWalking_2.gxx : bizarrerie 30 10 97 "<<std::endl;
- }
-#endif
- }
-
- return;
- }
- Up = Uc;
- Vp = Vc;
- }
-
- // now the last point of the line and the last calculated point are compated.
- // there will be no need to "Cut"
-
- gp_Vec2d aVec1 (Up-wd1[i].ustart, Vp-wd1[i].vstart),
- aVec2 (UV(1)-wd1[i].ustart, UV(2)-wd1[i].vstart);
- CutVectorByTolerances (aVec1, tolerance);
- CutVectorByTolerances (aVec2, tolerance);
-
- Scal = aVec1 * aVec2;
-
- if (Scal < 0) {
- Irang = i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- }
- else if (Abs(UV(1)-wd1[i].ustart) < tolerance(1) &&
- Abs(UV(2)-wd1[i].vstart) < tolerance(2)) {
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- }
- else if (nbMultiplicities[i] > 0) {
- for (Standard_Integer j = N+1; j <= N+nbMultiplicities[i]; j++) {
-
- aVec1.SetCoord (Up-Umult(j), Vp-Vmult(j));
- aVec2.SetCoord (UV(1)-Umult(j), UV(2)-Vmult(j));
- CutVectorByTolerances (aVec1, tolerance);
- CutVectorByTolerances (aVec2, tolerance);
-
- Scal = aVec1 * aVec2;
-
- if (Scal < 0) {
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- break;
- }
- else if (Abs(UV(1)-Umult(j)) < tolerance(1) &&
- Abs(UV(2)-Vmult(j)) < tolerance(2)) {
- Irang=i;
- UV(1) = wd1[Irang].ustart;
- UV(2) = wd1[Irang].vstart;
- Found = Standard_True;
- break;
- }
- }
- }
- if (Found) {
- Irang = -Irang; // jag 941017
- Standard_Real abidF[1], abidD[1][2];
- math_Vector bidF(abidF,1,1);
- math_Matrix bidD(abidD,1,1,1,2);
- sp.Values(UV,bidF,bidD);
- return;
- }
- }
- }
-}
-
-
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <NCollection_IncAllocator.hxx>
-#include <NCollection_LocalArray.hxx>
-
-
-// modified by NIZHNY-MKK Thu Nov 2 15:07:26 2000.BEGIN
-static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
- const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const Standard_Real& prevUp,
- const Standard_Real& prevVp,
- const IntWalk_VectorOfInteger& nbMultiplicities,
- const math_Vector& tolerance,
- TheIWFunction& sp,
- math_Vector& UV,
- Standard_Integer& Irang);
-// modified by NIZHNY-MKK Thu Nov 2 15:07:39 2000.END
-
-
-void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const ThePOPIterator& Pnts1,
- TheIWFunction& Func,
- Standard_Boolean& Rajout)
-
-// Processing of open line.
-//
-// 1) for any starting point, which is not passing and not tangent and not yet processed,
-// calculation of the step of advancement = step depending on the arrow and the maximum step.
-//
-// 2) calculate a point of approach (this point is on the tangent to the section
-// of distance = no point in the interior)
-//
-// 3) conditions {
-// (all calculated points do not exceed a point in the
-// list of starting points)
-// or
-// (all points do not form an open line going
-// from one border of the domain to the other or from a point tangent
-// to border or from 2 tangent points : single cases)
-//
-// 1) framing of approached point on borders if necessary (there is
-// calculation of step)
-// 2) calculation of the point
-// 3) if the point is not found the step is divided
-// 4) stop tests
-// 5) calculation of the step depending on the arrow and the max step,
-// (TestDeflection)
-// stop possible.
-// end of conditions.
-
-{
- Standard_Integer I = 0, N = 0, SaveN = 0;
- Standard_Real aBornInf[2] = {}, aBornSup[2] = {}, aUVap[2] = {};
- math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2), UVap(aUVap,1,2);
- Standard_Real PasC = 0.0, PasCu = 0.0, PasCv = 0.0;
- Standard_Boolean Arrive = false; // shows if the line ends
- Standard_Boolean Cadre = false; // shows if one is on border of the domain
- Standard_Boolean ArretAjout = false; //shows if one is on added point
- IntSurf_PntOn2S Psol;
- Handle(IntWalk_TheIWLine) CurrentLine; // line under construction
- Standard_Boolean Tgtend = false;
-
- IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent = IntWalk_OK;
-
- Standard_Integer NbDivision = 0;
- // number of divisions of step for each section
-
- Standard_Integer StepSign = 0;
-
- ThePointOfPath PathPnt;
-
- BornInf(1) = Um;
- BornSup(1) = UM;
- BornInf(2) = Vm;
- BornSup(2) = VM;
-
- math_FunctionSetRoot Rsnld(Func, tolerance);
- Standard_Integer nbPath = Pnts1.Length();
-
- // modified by NIZHNY-MKK Fri Oct 27 12:32:34 2000.BEGIN
- NCollection_LocalArray<Standard_Integer> movementdirectioninfoarr (nbPath + 1);
- Standard_Integer* movementdirectioninfo = movementdirectioninfoarr;
- for (I = 0; I <= nbPath; I++) {
- movementdirectioninfo[I] = 0;
- }
- // modified by NIZHNY-MKK Fri Oct 27 12:32:38 2000.END
-
- TheIWFunction aFuncForDuplicate = Func;
-
- for (I = 1; I <= nbPath; I++) {
- //start point of the progression
- // if (wd1[I].etat > 11) {
- // modified by NIZHNY-MKK Fri Oct 27 12:33:37 2000.BEGIN
- if ((wd1[I].etat > 11) || ((wd1[I].etat < -11) && (movementdirectioninfo[I]!=0))) {
- // modified by NIZHNY-MKK Fri Oct 27 12:33:43 2000.END
- PathPnt = Pnts1.Value(I);
- UVap(1) = wd1[I].ustart;
- UVap(2) = wd1[I].vstart;
- MakeWalkingPoint(11, UVap(1), UVap(2), Func, previousPoint);
-
- if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
- {
- wd1[I].etat = -Abs(wd1[I].etat); //mark point as processed
- continue;
- }
-
- CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
- CurrentLine->SetTangencyAtBegining(Standard_False);
- Tgtend = Standard_False;
- CurrentLine->AddStatusFirst(Standard_False, Standard_True, I, PathPnt);
- previousd3d = Func.Direction3d();
- previousd2d = Func.Direction2d();
- CurrentLine->AddPoint(previousPoint);
- // modified by NIZHNY-MKK Fri Oct 27 12:34:32 2000.BEGIN
- if(movementdirectioninfo[I] !=0) {
- if(movementdirectioninfo[I] < 0) {
- StepSign = -1;
- CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
- } else {
- StepSign = 1;
- CurrentLine->SetTangentVector(previousd3d,1);
- }
- } else {
- Standard_Real tyutuyt=ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
- if( tyutuyt < 0) {
- StepSign = -1;
- CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
- }
- else {
- StepSign = 1;
- CurrentLine->SetTangentVector(previousd3d,1);
- }
- }
- // modified by NIZHNY-MKK Fri Oct 27 12:34:37 2000.END
-
- // Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
- wd1[I].etat = -Abs(wd1[I].etat);
- movementdirectioninfo[I] = (movementdirectioninfo[I]==0) ? StepSign : 0;
-// Modified by Sergey KHROMOV - Tue Nov 20 10:41:56 2001 End
- // first step of advancement
- Standard_Real d2dx = Abs(previousd2d.X());
- Standard_Real d2dy = Abs(previousd2d.Y());
- if (d2dx < tolerance(1)) {
- PasC = pas * (VM-Vm)/d2dy;
- }
- else if (d2dy < tolerance(2)) {
- PasC = pas * (UM-Um)/d2dx;
- }
- else {
- PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
- }
-
- Arrive = Standard_False;
- ArretAjout = Standard_False;
- NbDivision = 0;
- StatusPrecedent = IntWalk_OK;
- // modified by NIZHNY-MKK Fri Oct 27 12:39:37 2000
- Standard_Integer IndexOfPathPointDoNotCheck=0;
- Standard_Integer aNbIter = 10;
- while (!Arrive) { // as one of stop tests is not checked
- Cadre = Cadrage(BornInf,BornSup,UVap,PasC,StepSign);
- // Border?
-
-#ifdef CHRONO
- Chronrsnld.Start();
-#endif
-
- Rsnld.Perform(Func,UVap,BornInf,BornSup);
-
-#ifdef CHRONO
- Chronrsnld.Stop();
-#endif
-
- if (Cadre) {
- BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM;
- }
- if (Rsnld.IsDone()) {
- if (Abs(Func.Root()) > Func.Tolerance()) {
- PasC = PasC / 2.0;
- PasCu = Abs(PasC*previousd2d.X());
- PasCv = Abs(PasC*previousd2d.Y());
- if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
- if (CurrentLine->NbPoints() == 1) break;
- Arrive = Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True; // check
- Rajout = Standard_True;
- seqAlone.Append(lines.Length() + 1);
- seqAjout.Append(lines.Length() + 1);
- }
- }
- else { // test stop
- Rsnld.Root(UVap);
- Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
- if (Arrive) {
- Cadre = Standard_False;
- //in case if there is a frame and arrive at the same time
- }
- else {
- if (Rajout) {
- ArretAjout =TestArretAjout(Func, UVap, N, Psol);
- SaveN = N;
- if (ArretAjout) {
- // jag 940615
- Tgtend = lines.Value(N)->IsTangentAtEnd();
- N = -N;
- }
- }
- // modified by NIZHNY-MKK Thu Nov 2 15:09:08 2000.BEGIN
- if(!(Rajout && ArretAjout)) {
- Standard_Real prevUp, prevVp;
- if (!reversed) {
- previousPoint.ParametersOnS2(prevUp, prevVp);
- }
- else {
- previousPoint.ParametersOnS1(prevUp, prevVp);
- }
- Arrive = TestPassedSolutionWithNegativeState(wd1, Umult, Vmult, prevUp, prevVp,
- nbMultiplicities, tolerance, Func, UVap, N);
- if(Arrive) {
- Cadre = Standard_False;
- }
- }
- // modified by NIZHNY-MKK Thu Nov 2 15:09:13 2000.END
- if (!ArretAjout && Cadre) {
- if (CurrentLine->NbPoints() == 1) break; // cancel the line
- TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
- // if (N == 0) {
- if (N <= 0) { // jag 941017
- MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
- Tgtend = Func.IsTangent();
- N = -N;
- }
- }
- }
- aStatus = TestDeflection(Func, Arrive, UVap, StatusPrecedent,
- NbDivision,PasC,StepSign);
- StatusPrecedent = aStatus;
- if (aStatus == IntWalk_PasTropGrand) {
- Arrive = Standard_False;
- ArretAjout = Standard_False;
- Tgtend = Standard_False; // jag 940615
- if (!reversed) {
- previousPoint.ParametersOnS2(UVap(1), UVap(2));
- }
- else {
- previousPoint.ParametersOnS1(UVap(1), UVap(2));
- }
- }
- else if (ArretAjout || Cadre) {
- Arrive = Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- //if (aStatus != IntWalk_ArretSurPointPrecedent)
- CurrentLine->AddPoint(Psol);
- //Remove <SaveN> from <seqAlone>
- for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
- if (seqAlone(iseq) == SaveN)
- {
- seqAlone.Remove(iseq);
- break;
- }
-
- if (Cadre && N==0) {
- Rajout = Standard_True;
- seqAjout.Append(lines.Length()+1);
- }
- }
- else if (aStatus == IntWalk_ArretSurPointPrecedent) {
- if (CurrentLine->NbPoints() == 1) { //cancel the line
- Arrive = Standard_False;
- break;
- }
- Arrive = Standard_True;
- Rajout = Standard_True;
- //AddAlonePoint();
- seqAlone.Append(lines.Length() + 1);
- seqAjout.Append(lines.Length() + 1);
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True; // check
- }
- else if (Arrive) {
- if (CurrentLine->NbPoints() == 1 && // cancel the line
- (N == I || aStatus == IntWalk_PointConfondu) ) {
- // if N == I the main uv is probably lost
- // or the point is a point of accumulation
- // if point is confused the start data is bad
- Arrive = Standard_False;
- break;
- }
- // necessarily N > 0 jag 940617
- // point of stop given at input
- PathPnt = Pnts1.Value(N);
-
- Standard_Integer etat1N=wd1[N].etat;
- // modified by NIZHNY-MKK Thu Nov 2 15:09:51 2000.BEGIN
- // if (etat1N < 11) { // passing point that is a stop
- if (Abs(etat1N) < 11) { // passing point that is a stop
- // modified by NIZHNY-MKK Thu Nov 2 15:12:11 2000.END
- if (aStatus == IntWalk_ArretSurPoint) {
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True; // need check
- }
- else {
- Arrive = Standard_False;
- }
- CurrentLine->AddIndexPassing(N);
- }
- else { // point of stop given at input
- if (etat1N == 11) {
- Tgtend = Standard_True;
- }
- CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
- }
- AddPointInCurrentLine(N,PathPnt,CurrentLine);
- if ((etat1N != 1 && etat1N != 11)) {
- // modified by NIZHNY-MKK Fri Oct 27 12:43:05 2000.BEGIN
- // wd1[N].etat= - wd1[N].etat;
- wd1[N].etat = - Abs(etat1N);
- movementdirectioninfo[N] = (movementdirectioninfo[N]==0) ? StepSign : 0;
- if(Arrive && movementdirectioninfo[N]!=0) {
- IndexOfPathPointDoNotCheck = N;
- }
-
- if(Arrive) {
- Rajout = Standard_True;
- seqAjout.Append(lines.Length() + 1);
- }
- // modified by NIZHNY-MKK Fri Oct 27 12:45:33 2000.END
- }
- }
- else if (aStatus == IntWalk_ArretSurPoint) {
- Arrive = Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True;
- MakeWalkingPoint(1, UVap(1), UVap(2), Func, Psol);
- CurrentLine->AddPoint(Psol);
- Rajout = Standard_True;
- seqAlone.Append(lines.Length() + 1);
- seqAjout.Append(lines.Length() + 1);
- }
- else if (aStatus == IntWalk_OK) {
- MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
- previousd3d = Func.Direction3d();
- previousd2d = Func.Direction2d();
- CurrentLine->AddPoint(previousPoint);
- }
- else if (aStatus == IntWalk_PointConfondu)
- {
- aNbIter --;
- }
- }
- }
- else { // no numerical solution
- PasC = PasC / 2.;
- PasCu = Abs(PasC*previousd2d.X());
- PasCv = Abs(PasC*previousd2d.Y());
- if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
- if (CurrentLine->NbPoints()==1) break;
- Arrive = Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True; // need check
- Rajout = Standard_True;
- seqAlone.Append(lines.Length() + 1);
- seqAjout.Append(lines.Length() + 1);
- }
- }
-
- if(aNbIter < 0)
- break;
- } // end of started line
-
- if (Arrive) {
- CurrentLine->SetTangencyAtEnd(Tgtend);
- lines.Append(CurrentLine);
- // modified by NIZHNY-MKK Fri Oct 27 12:59:29 2000.BEGIN
- movementdirectioninfo[I]=0;
- if(wd1[I].etat > 0)
- // modified by NIZHNY-MKK Fri Oct 27 12:59:42 2000.END
- wd1[I].etat=-wd1[I].etat;
-
- //-- lbr le 5 juin 97 (Pb ds Contap)
- for(Standard_Integer av=1; av<=nbPath; av++) {
- // modified by NIZHNY-MKK Fri Oct 27 13:00:22 2000.BEGIN
- // if (wd1[av].etat > 11) {
- if ((wd1[av].etat > 11) ||
- ((av!=I) &&
- (av!=IndexOfPathPointDoNotCheck) &&
- (wd1[av].etat < -11) &&
- (movementdirectioninfo[av]!=0)))
- {
- // modified by NIZHNY-MKK Fri Oct 27 13:00:26 2000.END
- Standard_Real Uav=wd1[av].ustart;
- Standard_Real Vav=wd1[av].vstart;
- Standard_Real Uavp,Vavp;
- const IntSurf_PntOn2S &avP=CurrentLine->Value(CurrentLine->NbPoints());
- if (!reversed) {
- avP.ParametersOnS2(Uavp,Vavp);
- }
- else {
- avP.ParametersOnS1(Uavp,Vavp);
- }
- Uav-=Uavp;
- Vav-=Vavp;
- Uav*=0.001; Vav*=0.001;
- if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) {
- // modified by NIZHNY-MKK Fri Oct 27 13:01:38 2000.BEGIN
- // wd1[av].etat=-wd1[av].etat;
- if(wd1[av].etat < 0) {
- movementdirectioninfo[av] = 0;
- } else {
- wd1[av].etat=-wd1[av].etat;
- movementdirectioninfo[av] = StepSign;
- }
- // modified by NIZHNY-MKK Fri Oct 27 13:01:42 2000.END
- CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
- //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
- }
-
- const IntSurf_PntOn2S &avPP=CurrentLine->Value(1);
- if (!reversed) {
- avPP.ParametersOnS2(Uavp,Vavp);
- }
- else {
- avPP.ParametersOnS1(Uavp,Vavp);
- }
- Uav=wd1[av].ustart;
- Vav=wd1[av].vstart;
- Uav-=Uavp;
- Vav-=Vavp;
- Uav*=0.001; Vav*=0.001;
- if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) {
- // modified by NIZHNY-MKK Fri Oct 27 13:02:49 2000.BEGIN
- // wd1[av].etat=-wd1[av].etat;
- if(wd1[av].etat < 0) {
- movementdirectioninfo[av] = 0;
- } else {
- wd1[av].etat=-wd1[av].etat;
- movementdirectioninfo[av] = -StepSign;
- }
- // modified by NIZHNY-MKK Fri Oct 27 13:02:52 2000.END
- //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
- CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
- }
- }
- }
- }
- } //end of point processing
- } //end of all points
-}
-
-// modified by NIZHNY-MKK Thu Nov 2 15:07:53 2000.BEGIN
-static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
- const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const Standard_Real& prevUp,
- const Standard_Real& prevVp,
- const IntWalk_VectorOfInteger& nbMultiplicities,
- const math_Vector& tolerance,
- TheIWFunction& sp,
- math_Vector& UV,
- Standard_Integer& Irang) {
- Standard_Boolean Arrive = Standard_False;
- Standard_Real Dup, Dvp, Utest,Vtest;
- Standard_Real tolu = tolerance(1);
- Standard_Real tolv = tolerance(2);
- Standard_Integer i, j, k, N;
- for (i = 1; i < (int)wd.size(); i++) {
- if (wd[i].etat < -11) {
-
- // debug jag see with isg
-
- Utest = wd[i].ustart;
- Vtest = wd[i].vstart;
- Dup = prevUp - Utest;
- Dvp = prevVp - Vtest;
- if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv) {
- Standard_Real UV1mUtest = UV(1)-Utest;
- Standard_Real UV2mVtest = UV(2)-Vtest;
- if(( (Dup*UV1mUtest + Dvp*UV2mVtest) < 0) ||
- ( Abs(UV1mUtest) < tolu
- && Abs(UV2mVtest) < tolv)) {
- Irang=i;
- Arrive = Standard_True;
- UV(1) = Utest;
- UV(2) = Vtest;
- }
- else if (nbMultiplicities[i] > 0) {
- N=0;
- for (k = 1; k < i; k++) {
- N+=nbMultiplicities[k];
- }
- for (j = N + 1; j <= N + nbMultiplicities[i]; j++) {
- if (((prevUp-Umult(j))*(UV(1)-Umult(j)) +
- (prevVp-Vmult(j))*(UV(2)-Vmult(j)) < 0) ||
- (Abs(UV(1)-Umult(j)) < tolu &&
- Abs(UV(2)-Vmult(j)) < tolv)) {
- Irang=i;
- Arrive = Standard_True;
- UV(1) = Utest;
- UV(2) = Vtest;
- break;
- }
- }
- }
- if (Arrive) {
- Standard_Real abidF[1], abidD[1][2];
- math_Vector bidF(abidF,1,1);
- math_Matrix bidD(abidD,1,1,1,2);
- sp.Values(UV,bidF,bidD);
- break;
- }
- }
- }
- }
- return Arrive;
-}
-// modified by NIZHNY-MKK Thu Nov 2 15:07:58 2000.END
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 <NCollection_IncAllocator.hxx>
-
-void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
- const TColStd_SequenceOfReal& Vmult,
- const ThePOPIterator& Pnts1,
- const ThePOLIterator& Pnts2,
- TheIWFunction& Func,
- Standard_Boolean& Rajout )
-// *********** Processing of closed line **********************
-//
-// for any interior non-processed point
-// calculate the step of advancement=step depending on the arrow and max step
-// calculate a point of approach (this point is on the tangent to the section
-// of distance = no interior point)
-// conditions
-// (all calculated points do not form a closed loop)
-// or
-// (all points do not form an open line going from
-// one border of the domain to the other or from a point tangent
-// to the border or from 2 tangent points : single cases)
-//
-// frame the point of approach on borders if necessary
-// calculate the point
-// if point not found divide the step
-// test of stop
-// calculate step depending on the arrow and the max step (stop possible)
-//
-// ********************************************************************
-{
- Standard_Integer I = 0, N = 0,SaveN = 0;
- Standard_Real aBornInf[2] = {}, aBornSup[2] = {}, aUVap[2] = {};
- math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2);
- math_Vector Uvap(aUVap,1,2);// parameters of current approach
- Standard_Real PasC = 0.0; // step of advancement on the tangent
- Standard_Real PasCu = 0.0; // step of advancement current by U
- Standard_Real PasCv = 0.0; // step of advancement current by V
- Standard_Real PasSav = 0.0; // save first step of advancement
- Standard_Boolean Arrive = false;// show if line ends
- Standard_Boolean Cadre = false; // show if on border of the domains
- Standard_Boolean ArretAjout = false; // show if on the added point
- IntSurf_PntOn2S Psol;
- Handle(IntWalk_TheIWLine) CurrentLine; //line under construction
- ThePointOfPath PathPnt;
- ThePointOfLoop LoopPnt;
-
- Standard_Boolean Tgtbeg = false, Tgtend = false;
-
- Standard_Integer StepSign = 0;
-
- IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent;
- Standard_Integer NbDivision = 0; // number of divisions of step
- // during calculation of 1 section
-
- Standard_Integer Ipass = 0;
- //index in the iterator of points on edge of point of passage
-
-
- BornInf(1) = Um;
- BornSup(1) = UM;
- BornInf(2) = Vm;
- BornSup(2) = VM;
-
- math_FunctionSetRoot Rsnld(Func,tolerance);
- Standard_Integer nbLoop = Pnts2.Length();
-
- // Check borders for degeneracy:
- math_Matrix D(1,1,1,2);
- const Standard_Integer aNbSamplePnt = 10;
- Standard_Boolean isLeftDegeneratedBorder[2] = {Standard_True, Standard_True};
- Standard_Boolean isRightDegeneratedBorder[2] = {Standard_True, Standard_True};
- math_Vector aStep(1,2);
- aStep = (BornSup - BornInf) / (aNbSamplePnt - 1);
- for(Standard_Integer aBorderIdx = 1; aBorderIdx <= 2; aBorderIdx++)
- {
- Standard_Integer aChangeIdx = aBorderIdx == 2? 1 : 2;
- math_Vector UV(1,2);
-
- // Left border.
- UV(aBorderIdx) = BornInf(aBorderIdx);
- for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
- {
- Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
- UV(aChangeIdx) = aParam;
- Func.Derivatives(UV, D);
- if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion())
- {
- isLeftDegeneratedBorder[aBorderIdx - 1] = Standard_False;
- break;
- }
- }
-
- // Right border.
- UV(aBorderIdx) = BornSup(aBorderIdx);
- for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
- {
- Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
- UV(aChangeIdx) = aParam;
- Func.Derivatives(UV, D);
- if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion())
- {
- isRightDegeneratedBorder[aBorderIdx - 1] = Standard_False;
- break;
- }
- }
- }
-
- TheIWFunction aFuncForDuplicate = Func;
-
- for (I = 1;I<=nbLoop;I++) {
- if (wd2[I].etat > 12)
- { // start point of closed line
- LoopPnt = Pnts2.Value(I);
- previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt), reversed,
- wd2[I].ustart, wd2[I].vstart);
-
- if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
- {
- wd2[I].etat = -wd2[I].etat; //mark point as processed
- continue;
- }
-
- previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt);
- previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt);
-
- CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
- CurrentLine->AddPoint(previousPoint);
- CurrentLine->SetTangentVector(previousd3d,1);
- Tgtbeg = Standard_False;
- Tgtend = Standard_False;
- Uvap(1) = wd2[I].ustart;
- Uvap(2) = wd2[I].vstart;
-
- StepSign = 1;
-
- // first step of advancement
-
- Standard_Real d2dx = Abs(previousd2d.X());
- Standard_Real d2dy = Abs(previousd2d.Y());
- if (d2dx < tolerance(1)) {
- PasC = pas * (VM-Vm)/d2dy;
- }
- else if (d2dy < tolerance(2)) {
- PasC = pas * (UM-Um)/d2dx;
- }
- else {
- PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
- }
-
- PasSav = PasC;
-
- Arrive = Standard_False;
- ArretAjout = Standard_False;
- NbDivision = 0;
- StatusPrecedent = IntWalk_OK;
- Standard_Integer aNbIter = 10;
- while (!Arrive) { // as no test of stop is passed
- Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign); // border?
-#ifdef CHRONO
- Chronrsnld.Start();
-#endif
-
- Rsnld.Perform(Func,Uvap,BornInf,BornSup);
-
-#ifdef CHRONO
- Chronrsnld.Stop();
-#endif
- Standard_Boolean isOnDegeneratedBorder = Standard_False;
-
- if (Cadre) { // update of limits.
- BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
- }
- if (Rsnld.IsDone()) {
- if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
- PasC = PasC/2.;
- PasCu = Abs(PasC*previousd2d.X());
- PasCv = Abs(PasC*previousd2d.Y());
-
- if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
- if (CurrentLine->NbPoints()==1)
- {
- RemoveTwoEndPoints(I);
- break; //cancel the line
- }
- if (wd2[I].etat >12) { //the line should become open
- wd2[I].etat = 12; //declare it open
- ArretAjout = Standard_False;
- OpenLine(0,Psol,Pnts1,Func,CurrentLine);
- StepSign = -1;
- StatusPrecedent = IntWalk_OK;
- Arrive = Standard_False;
- PasC = PasSav;
- Rajout = Standard_True;
- seqAlone.Append(-lines.Length()-1);
- seqAjout.Append(-lines.Length()-1);
- }
- else { // line s is open
- Arrive =Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- Tgtend = Standard_True;
- }
- /*
- Arrive = Standard_True;
- CurrentLine->AddStatusFirstLast(Standard_False,
- Standard_False,Standard_False);
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- Tgtend = Standard_True;
- */
- }
- }
- else { // there is a solution
- Rsnld.Root(Uvap);
-
- // Avoid uninitialized memory access.
- if (CurrentLine->NbPoints() > 2)
- {
- for(Standard_Integer aCoordIdx = 1; aCoordIdx <= 2; aCoordIdx++)
- {
- // Check degenerated cases and fix if possible.
- if ( ( isLeftDegeneratedBorder[aCoordIdx - 1]
- && Abs (Uvap(aCoordIdx) - BornInf(aCoordIdx)) < Precision::PConfusion())||
- (isRightDegeneratedBorder[aCoordIdx - 1]
- && Abs (Uvap(aCoordIdx) - BornSup(aCoordIdx)) < Precision::PConfusion()) )
- {
- Standard_Real uvprev[2], uv[2];
- if (!reversed)
- {
- CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS2(uvprev[0], uvprev[1]);
- CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS2(uv[0], uv[1]);
- }
- else
- {
- CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS1(uvprev[0], uvprev[1]);
- CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS1(uv[0], uv[1]);
- }
-
- Standard_Real aScaleCoeff = 0.0;
-
- // Avoid finite cycle which lead to stop computing iline.
- if (aStatus != IntWalk_PasTropGrand)
- {
- // Make linear extrapolation.
- if ( Abs(uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) > gp::Resolution())
- aScaleCoeff = Abs ((Uvap(aCoordIdx) - uv[aCoordIdx - 1])
- / (uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) );
- Standard_Integer aFixIdx = aCoordIdx == 1? 2 : 1; // Fixing index;
- Uvap(aFixIdx) = uv[aFixIdx - 1] + (uv[aFixIdx - 1] - uvprev[aFixIdx - 1]) * aScaleCoeff;
- isOnDegeneratedBorder = Standard_True;
- }
- }
- }
- }
-
- Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
- if (Arrive) {//reset proper parameter to test the arrow.
- Psol = CurrentLine->Value(1);
- if (!reversed) {
- Psol.ParametersOnS2(Uvap(1),Uvap(2));
- }
- else {
- Psol.ParametersOnS1(Uvap(1),Uvap(2));
- }
- Cadre=Standard_False;
- //in case if there is a frame and arrival at the same time
- }
- else { // modif jag 940615
- if (Rajout) { // test on added points
- ArretAjout =TestArretAjout(Func,Uvap,N,Psol);
- SaveN = N;
- if (ArretAjout) {
- if (N >0) {
- Tgtend = lines.Value(N)->IsTangentAtEnd();
- N = -N;
- }
- else {
- Tgtend = lines.Value(-N)->IsTangentAtBegining();
- }
- Arrive = (wd2[I].etat == 12);
- }
- }
-
- if (!ArretAjout&& Cadre) { // test on already marked points
- if (CurrentLine->NbPoints() == 1)
- {
- RemoveTwoEndPoints(I);
- break; // cancel the line
- }
- TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
- SaveN = N;
- // if (N==0) {
- if (N <= 0) { // jag 941017
- MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
- Tgtend = Func.IsTangent(); // jag 940616
- if (isOnDegeneratedBorder)
- Tgtend = Standard_True;
- N = -N;
- }
- Arrive = (wd2[I].etat == 12); // the line is open
- }
- }
- aStatus = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
- NbDivision,PasC,StepSign);
-
- if (isOnDegeneratedBorder && Tgtend)
- aStatus = IntWalk_ArretSurPoint;
-
- StatusPrecedent = aStatus;
- if (aStatus == IntWalk_PasTropGrand) {// division of the step
- Arrive = Standard_False;
- ArretAjout = Standard_False;
- Tgtend = Standard_False; // jag 940616
- if (!reversed) {
- previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
- }
- else {
- previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
- }
- }
- else if (ArretAjout || Cadre) {
-
- if (Arrive) { // line s is open
- CurrentLine->AddStatusLast(Standard_False);
- //if (aStatus != IntWalk_ArretSurPointPrecedent)
- CurrentLine->AddPoint(Psol);
-
- //Remove <SaveN> from <seqAlone> and, if it is first found point,
- //from <seqAjout> too
- if (IsValidEndPoint(I, SaveN))
- {
- for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
- if (seqAlone(iseq) == SaveN)
- {
- seqAlone.Remove(iseq);
- break;
- }
- if (CurrentLine->NbPoints() <= 3)
- for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
- if (seqAjout(iseq) == SaveN)
- {
- seqAjout.Remove(iseq);
- break;
- }
- }
- else
- {
- if (seqAlone.Last() == -lines.Length()-1)
- {
- seqAlone.Remove(seqAlone.Length());
- seqAjout.Remove(seqAjout.Length());
- }
- RemoveTwoEndPoints(I);
- Arrive = Standard_False;
- break; //cancel the line
- }
-
- if (Cadre && N==0) {
- Rajout = Standard_True;
- //seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- }
-
- }
- else { // open
- wd2[I].etat = 12; // declare it open
- Tgtbeg = Tgtend;
- Tgtend = Standard_False;
- ArretAjout = Standard_False;
- StepSign = -1;
- StatusPrecedent = IntWalk_OK;
- PasC = PasSav;
- //Check if <Psol> has been really updated
- if (Arrive || Rajout || (!ArretAjout && Cadre && SaveN <= 0))
- {
- if (aStatus == IntWalk_ArretSurPointPrecedent) {
- CurrentLine->AddPoint(Psol);
- OpenLine(0,Psol,Pnts1,Func,CurrentLine);
- }
- else {
- OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
- }
- }
- //Remove <SaveN> from <seqAlone> and, if it is first found point,
- //from <seqAjout> too
- if (IsValidEndPoint(I, SaveN))
- {
- for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
- if (seqAlone(iseq) == SaveN)
- {
- seqAlone.Remove(iseq);
- break;
- }
- if (CurrentLine->NbPoints() <= 2)
- for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
- if (seqAjout(iseq) == SaveN)
- {
- seqAjout.Remove(iseq);
- break;
- }
- }
- else
- {
- RemoveTwoEndPoints(I);
- break; //cancel the line
- }
-
- if (Cadre && N==0) {
- Rajout = Standard_True;
- seqAjout.Append(-lines.Length()-1);
- }
- }
- }
- else if (aStatus == IntWalk_ArretSurPointPrecedent) {
- if (CurrentLine->NbPoints() == 1) { //cancel the line
- Arrive = Standard_False;
- RemoveTwoEndPoints(I);
- break;
- }
- if (wd2[I].etat >12) { //the line should become open
- wd2[I].etat = 12; //declare it open
- ArretAjout = Standard_False;
- OpenLine(0,Psol,Pnts1,Func,CurrentLine);
- StepSign = -1;
- StatusPrecedent = IntWalk_OK;
- Arrive = Standard_False;
- PasC = PasSav;
- Rajout = Standard_True;
- seqAlone.Append(-lines.Length()-1);
- seqAjout.Append(-lines.Length()-1);
- }
- else { // line s is open
- Arrive =Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- }
- }
- else if (Arrive) {
- if (wd2[I].etat > 12) { //line closed good case
- CurrentLine->AddStatusFirstLast(Standard_True,
- Standard_False,Standard_False);
- CurrentLine->AddPoint(CurrentLine->Value(1));
- }
- else if ((N >0) && (Pnts1.Length() >= N))
- {
- //point of stop given at input
- PathPnt = Pnts1.Value(N);
- CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
- AddPointInCurrentLine(N,PathPnt,CurrentLine);
- }
- }
- else if (aStatus == IntWalk_ArretSurPoint) {
- if (wd2[I].etat >12) { //line should become open
- wd2[I].etat = 12; //declare it open
- Tgtbeg = Standard_True;
- Tgtend = Standard_False;
- N= -lines.Length()-1;
- Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
- OpenLine(N,Psol,Pnts1,Func,CurrentLine);
- StepSign = -1;
- Rajout = Standard_True;
- seqAlone.Append(N);
- seqAjout.Append(N);
- StatusPrecedent = IntWalk_OK;
- Arrive = Standard_False;
- PasC = PasSav;
- }
- else {
- Arrive = Standard_True;
- if (Ipass!=0) { //point of passage, point of stop
- PathPnt = Pnts1.Value(Ipass);
- CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
- AddPointInCurrentLine(Ipass,PathPnt,CurrentLine);
- }
- else {
- CurrentLine->AddStatusLast(Standard_False);
- IntSurf_PntOn2S newP;
- newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
- CurrentLine->AddPoint(newP);
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- }
- }
- }
- else if (aStatus == IntWalk_OK) {
- if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
- previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
- previousd3d = Func.Direction3d();
- previousd2d = Func.Direction2d();
- CurrentLine->AddPoint(previousPoint);
- }
- else if (aStatus == IntWalk_PointConfondu)
- {
- aNbIter --;
- }
- }
- }
- else { //no numerical solution NotDone
- PasC = PasC/2.;
- PasCu = Abs(PasC*previousd2d.X());
- PasCv = Abs(PasC*previousd2d.Y());
-
- if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
- if (CurrentLine->NbPoints() == 1)
- {
- RemoveTwoEndPoints(I);
- break; // cancel the line
- }
- if (wd2[I].etat >12) { //the line should become open
- wd2[I].etat = 12; //declare it open
- ArretAjout = Standard_False;
- OpenLine(0,Psol,Pnts1,Func,CurrentLine);
- StepSign = -1;
- StatusPrecedent = IntWalk_OK;
- Arrive = Standard_False;
- PasC = PasSav;
- Rajout = Standard_True;
- seqAlone.Append(-lines.Length()-1);
- seqAjout.Append(-lines.Length()-1);
- }
- else { // line s is open
- Arrive =Standard_True;
- CurrentLine->AddStatusLast(Standard_False);
- Tgtend = Standard_True;
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- }
- /*
- Arrive = Standard_True;
- CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
- Standard_False);
- Tgtend = Standard_True;
- Rajout = Standard_True;
- seqAlone.Append(lines.Length()+1);
- seqAjout.Append(lines.Length()+1);
- */
- }
- }
-
- if(aNbIter < 0)
- break;
- }// end of started line
- if (Arrive) {
- CurrentLine->SetTangencyAtBegining(Tgtbeg);
- CurrentLine->SetTangencyAtEnd(Tgtend);
-
- lines.Append(CurrentLine);
- wd2[I].etat=-wd2[I].etat; //mark point as processed
- }
- } //end of processing of start point
- } //end of all start points
-}
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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.
-
-namespace {
- static const Standard_Real CosRef3D = 0.98;// rule by tests in U4
- // correspond to 11.478 d
- static const Standard_Real CosRef2D = 0.88; // correspond to 25 d
- static const Standard_Integer MaxDivision = 60; // max number of step division
- // because the angle is too great in 2d (U4)
-}
-
-IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
- (TheIWFunction& sp,
- const Standard_Boolean Finished,
- const math_Vector& UV,
- const IntWalk_StatusDeflection StatusPrecedent,
- Standard_Integer& NbDivision,
- Standard_Real& Step,
- const Standard_Integer StepSign)
-{
- // Check the step of advancement, AND recalculate this step :
- //
- // 1) test point confused
- // if yes other tests are not done
- // 2) test angle 3d too great
- // if yes divide the step and leave
- // angle3d = angle ((previous point, calculated point),
- // previous tangent)
- // 3) check step of advancement in 2d
- // 4) test point confused
- // 5) test angle 2d too great
- // 6) test point of tangency
- // if yes leave
- // 7) calculate the tangent by u,v of the section
- // 8) test angle 3d too great
- // angle3d = angle ((previous point, calculated point),
- // new tangent)
- // 9) test angle 2d too great
- //10) test change of side (pass the tangent point not knowing it)
- //11) calculate the step of advancement depending on the vector
- //12) adjust the step depending on the previous steps
-
- IntWalk_StatusDeflection aStatus = IntWalk_OK;
-
- //---------------------------------------------------------------------------------
- //-- lbr le 4 Avril 95 : it is possible that the status returns points confused
- //-- if epsilon is great enough (1e-11). In this case one loops
- //-- without ever changing the values sent to Rsnld.
- //---------------------------------------------------------------------------------
- Standard_Real Paramu = 0.0, Paramv = 0.0;
-
- if (!reversed) {
- previousPoint.ParametersOnS2(Paramu, Paramv);
- }
- else
- {
- previousPoint.ParametersOnS1(Paramu, Paramv);
- }
-
- const Standard_Real Du = UV(1) - Paramu;
- const Standard_Real Dv = UV(2) - Paramv;
- const Standard_Real Duv = Du * Du + Dv * Dv;
-
- gp_Vec Corde(previousPoint.Value(), sp.Point());
-
- const Standard_Real Norme = Corde.SquareMagnitude();
-
- if ((Norme <= 4.0*Precision::SquareConfusion()) &&
- ((Duv <= Precision::SquarePConfusion()) || (StatusPrecedent != IntWalk_OK)))
- { // the square is already taken in the constructor
- aStatus = IntWalk_PointConfondu;
- if (StatusPrecedent == IntWalk_PasTropGrand)
- {
- return IntWalk_ArretSurPointPrecedent;
- }
- }
- else
- {
- Standard_Real Cosi = Corde * previousd3d;
- Standard_Real Cosi2 = 0.0;
-
- if (Cosi*StepSign >= 0.) {// angle 3d <= pi/2 !!!!
- const Standard_Real aDiv = previousd3d.SquareMagnitude()*Norme;
- if(aDiv == 0)
- return aStatus;
- Cosi2 = Cosi * Cosi / aDiv;
- }
- if (Cosi2 < CosRef3D) { //angle 3d too great
- Step = Step /2.0;
- Standard_Real StepU = Abs(Step*previousd2d.X()),
- StepV = Abs(Step*previousd2d.Y());
- if (StepU < tolerance(1) && StepV < tolerance(2))
- aStatus = IntWalk_ArretSurPointPrecedent;
- else
- aStatus = IntWalk_PasTropGrand;
- return aStatus;
- }
- }
-
- const Standard_Real aMinTolU = 0.1*Abs(Step*previousd2d.X()),
- aMinTolV = 0.1*Abs(Step*previousd2d.Y());
- const Standard_Real aTolU = (aMinTolU > 0.0) ? Min(tolerance(1), aMinTolU) : tolerance(1),
- aTolV = (aMinTolV > 0.0) ? Min(tolerance(2), aMinTolV) : tolerance(2);
-
- //If aMinTolU==0.0 then (Abs(Du) < aMinTolU) is equivalent of (Abs(Du) < 0.0).
- //It is impossible. Therefore, this case should be processed separately.
- //Analogically for aMinTolV.
-
- if ((Abs(Du) < aTolU) && (Abs(Dv) < aTolV))
- {
- //Thin shapes (for which Ulast-Ufirst or/and Vlast-Vfirst is quite small)
- //exists (see bug #25820). In this case, step is quite small too.
- //Nevertheless, it not always means that we mark time. Therefore, Du and Dv
- //must consider step (aMinTolU and aMinTolV parameters).
-
- return IntWalk_ArretSurPointPrecedent; //confused point 2d
- }
-
- Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
-
- if (Cosi < 0 && aStatus == IntWalk_PointConfondu)
- return IntWalk_ArretSurPointPrecedent; // leave as step back
- // with confused point
-
- if (sp.IsTangent())
- return IntWalk_ArretSurPoint;
-
-//if during routing one has subdivided more than MaxDivision for each
-//previous step, bug on the square; do nothing (experience U4)
-
- if ((NbDivision < MaxDivision) && (aStatus != IntWalk_PointConfondu) &&
- (StatusPrecedent!= IntWalk_PointConfondu))
- {
- Standard_Real Cosi2 = Cosi * Cosi / Duv;
- if (Cosi2 < CosRef2D || Cosi < 0 ) {
- Step = Step / 2.0;
- Standard_Real StepU = Abs(Step*previousd2d.X()),
- StepV = Abs(Step*previousd2d.Y());
-
- if (StepU < tolerance(1) && StepV < tolerance(2))
- aStatus = IntWalk_ArretSurPointPrecedent;
- else
- aStatus = IntWalk_PasTropGrand;
- NbDivision = NbDivision + 1;
- return aStatus;
- }
-
- Cosi = Corde * sp.Direction3d();
- Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
- if (Cosi2 < CosRef3D ){ //angle 3d too great
- Step = Step / 2.;
- Standard_Real StepU = Abs(Step*previousd2d.X()),
- StepV = Abs(Step*previousd2d.Y());
- if (StepU < tolerance(1) && StepV < tolerance(2))
- aStatus = IntWalk_ArretSurPoint;
- else
- aStatus = IntWalk_PasTropGrand;
- return aStatus;
- }
- Cosi = Du * sp.Direction2d().X() +
- Dv * sp.Direction2d().Y();
- Cosi2 = Cosi * Cosi / Duv;
- if (Cosi2 < CosRef2D ||
- sp.Direction2d() * previousd2d < 0) {
- //angle 2d too great or change the side
- Step = Step / 2.;
- Standard_Real StepU = Abs(Step*previousd2d.X()),
- StepV = Abs(Step*previousd2d.Y());
- if (StepU < tolerance(1) && StepV < tolerance(2))
- aStatus = IntWalk_ArretSurPointPrecedent;
- else
- aStatus = IntWalk_PasTropGrand;
- return aStatus;
- }
- }
-
- if (!Finished) {
- if (aStatus == IntWalk_PointConfondu)
- {
- Standard_Real StepU = Min(Abs(1.5 * Du),pas*(UM-Um)),
- StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
-
- Standard_Real d2dx = Abs(previousd2d.X());
- Standard_Real d2dy = Abs(previousd2d.Y());
-
- if (d2dx < tolerance(1))
- {
- Step = StepV/d2dy;
- }
- else if (d2dy < tolerance(2))
- {
- Step = StepU/d2dx;
- }
- else
- {
- Step = Min(StepU/d2dx,StepV/d2dy);
- }
- }
- else
- {
- // estimate the current vector.
- // if vector/2<=current vector<= vector it is considered that the criterion
- // is observed.
- // otherwise adjust the step depending on the previous step
-
- /*
- Standard_Real Dist = Sqrt(Norme)/3.;
- TColgp_Array1OfPnt Poles(1,4);
- gp_Pnt POnCurv,Milieu;
- Poles(1) = previousPoint.Value();
- Poles(4) = sp.Point();
- Poles(2) = Poles(1).XYZ() +
- StepSign * Dist* previousd3d.Normalized().XYZ();
- Poles(3) = Poles(4).XYZ() -
- StepSign * Dist*sp.Direction3d().Normalized().XYZ();
- BzCLib::PntPole(0.5,Poles,POnCurv);
- Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
- // FlecheCourante = Milieu.Distance(POnCurv);
- Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
- */
-
- // Direct calculation :
- // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
- // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
- // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
- // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
- // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
- // the norm (square) of 3.*lambda (d1 - d4)/8.
- // either the norm of :
- // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
- // which produces, taking the square :
- // Norme * (d1-d4).SquareMagnitude()/64.
-
- Standard_Real FlecheCourante =
- (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
-
-
-// if (FlecheCourante <= 0.5*fleche) {
- if (FlecheCourante <= 0.25*fleche*fleche)
- {
- Standard_Real d2dx = Abs(sp.Direction2d().X());
- Standard_Real d2dy = Abs(sp.Direction2d().Y());
-
- Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
- StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
-
- if (d2dx < tolerance(1))
- {
- Step = StepV/d2dy;
- }
- else if (d2dy < tolerance(2))
- {
- Step = StepU/d2dx;
- }
- else
- {
- Step = Min(StepU/d2dx,StepV/d2dy);
- }
- }
- else
- {
- //if (FlecheCourante > fleche) { // step too great
- if (FlecheCourante > fleche*fleche)
- { // step too great
- Step = Step /2.;
- Standard_Real StepU = Abs(Step*previousd2d.X()),
- StepV = Abs(Step*previousd2d.Y());
-
- if (StepU < tolerance(1) && StepV < tolerance(2))
- aStatus = IntWalk_ArretSurPointPrecedent;
- else
- aStatus = IntWalk_PasTropGrand;
- }
- else
- {
- Standard_Real d2dx = Abs(sp.Direction2d().X());
- Standard_Real d2dy = Abs(sp.Direction2d().Y());
-
- Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
- StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
-
- if (d2dx < tolerance(1))
- {
- Step = Min(Step,StepV/d2dy);
- }
- else if (d2dy < tolerance(2))
- {
- Step = Min(Step,StepU/d2dx);
- }
- else
- {
- Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
- }
- }
- }
- }
- }
- return aStatus;
-}
+++ /dev/null
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 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 OCCT_DEBUG
-#define No_Standard_RangeError
-#define No_Standard_OutOfRange
-#endif
-
-
-void IntWalk_IWalking::AddPointInCurrentLine
- (const Standard_Integer N,
- const ThePointOfPath& PathPnt,
- const Handle(IntWalk_TheIWLine)& CurrentLine) const {
-
-
- IntSurf_PntOn2S Psol;
- Psol.SetValue(ThePointOfPathTool::Value3d(PathPnt),
- reversed,wd1[N].ustart,wd1[N].vstart);
- CurrentLine->AddPoint(Psol);
-}
-
-
-void IntWalk_IWalking::MakeWalkingPoint
- (const Standard_Integer Case,
- const Standard_Real U,
- const Standard_Real V,
- TheIWFunction& sp,
- IntSurf_PntOn2S& Psol )
-
-{
-
-// Case == 1 : make a WalkinkPoint.
-// Case == 2 : make a WalkinkPoint.
-// The computation of the tangency on is done
-// Case == 10 + i : make a WalkinkPoint according to i.
-// but F is updated according to U and V
-// Case == other : the exception Standard_Failure is raised.
-
- if ((Case == 1) || (Case == 2))
- {
- Psol.SetValue(sp.Point(), reversed, U, V);
- }
- else if (Case == 11 || Case == 12)
- {
- Standard_Real aUV[2] = {}, aFF[1] = {}, aDD[1][2] = {};
- math_Vector UV(aUV, 1, 2);
- math_Vector FF(aFF, 1, 1);
- math_Matrix DD(aDD, 1, 1, 1, 2);
- UV(1) = U;
- UV(2) = V;
- sp.Values(UV, FF, DD);
- MakeWalkingPoint(Case - 10, U, V, sp, Psol);
- }
- else
- {
- throw Standard_ConstructionError();
- }
-}
-
-
-
-void IntWalk_IWalking::OpenLine(const Standard_Integer N,
- const IntSurf_PntOn2S& Psol,
- const ThePOPIterator& Pnts1,
- TheIWFunction& sp,
- const Handle(IntWalk_TheIWLine)& Line )
-// **************** open the line and restart in the other direction********
-
-{
- ThePointOfPath PathPnt;
-
- Standard_Real aUV[2], aFF[1], aDD[1][2];
- math_Vector UV(aUV,1, 2);
- math_Vector FF(aFF,1, 1);
- math_Matrix DD(aDD,1, 1, 1, 2);
-
- previousPoint = Line->Value(1);
- if (!reversed) {
- previousPoint.ParametersOnS2(UV(1),UV(2));
- }
- else {
- previousPoint.ParametersOnS1(UV(1),UV(2));
- }
- sp.Values(UV, FF, DD);
- previousd3d = sp.Direction3d();
- previousd2d = sp.Direction2d();
-
- if (N>0) { //departure point given at input
- PathPnt = Pnts1.Value(N);
- //mark the line as open with a given stop point
- Line->AddStatusFirst(Standard_False,Standard_True,N,PathPnt);
-
-
- AddPointInCurrentLine(N,PathPnt,Line);
-
- }
- else {
- if (N <0) Line->AddPoint(Psol);
- Line->AddStatusFirst(Standard_False,Standard_False);
- //mark the line as open without given stop point
- }
- Line->Reverse(); //inverser la ligne
- Line->SetTangentVector(previousd3d.Reversed(),Line->NbPoints());
-}
-
-Standard_Boolean IntWalk_IWalking::IsValidEndPoint(const Standard_Integer IndOfPoint,
- const Standard_Integer IndOfLine)
-{
- if (PointLineLine.IsEmpty())
- return Standard_True;
-
- TColStd_ListIteratorOfListOfInteger itl(PointLineLine(IndOfPoint));
- for (; itl.More(); itl.Next())
- if (itl.Value() == IndOfLine)
- {
- PointLineLine(IndOfPoint).Remove(itl);
- return Standard_True;
- }
- return Standard_False;
-}
-
-void IntWalk_IWalking::RemoveTwoEndPoints(const Standard_Integer IndOfPoint)
-{
- if (PointLineLine.IsBound(IndOfPoint))
- {
- Standard_Integer Line1 = PointLineLine(IndOfPoint).First();
- Standard_Integer Line2 = PointLineLine(IndOfPoint).Last();
- for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
- {
- if (seqAlone(iseq) == Line1 ||
- seqAlone(iseq) == Line2)
- seqAlone.Remove(iseq--);
- }
- }
-}
-
-Standard_Boolean IntWalk_IWalking::IsPointOnLine(const gp_Pnt2d& theP2d,
- const Standard_Integer Irang)
-{
- const Handle(IntWalk_TheIWLine)& aLine = lines.Value(Abs(Irang));
- for (Standard_Integer i = 1; i <= aLine->NbPoints(); i++)
- {
- gp_Pnt2d P2d1 = aLine->Value(i).ValueOnSurface(reversed);
- if (Abs(P2d1.X() - theP2d.X()) <= tolerance(1) &&
- Abs(P2d1.Y() - theP2d.Y()) <= tolerance(2))
- return Standard_True;
- if (i < aLine->NbPoints())
- {
- gp_Pnt2d P2d2 = aLine->Value(i+1).ValueOnSurface(reversed);
- gp_Vec2d PP1(theP2d, P2d1);
- gp_Vec2d PP2(theP2d, P2d2);
- if (PP1 * PP2 < 0)
- return Standard_True;
- }
- }
- return Standard_False;
-}
-
-//==================================================================================
-//function : IsPointOnLine
-//purpose : Projects thePOn2S on the nearest segment of the already computed line.
-// The retrieved projection point (aPa) is refined using theSolver.
-// After the refinement, we will obtain a point aPb.
-// If thePOn2S is quite far from aPb then thePOn2S is not
-// in the line.
-// Every already computed line is checked.
-//==================================================================================
-Standard_Boolean IntWalk_IWalking::IsPointOnLine(const IntSurf_PntOn2S& thePOn2S,
- const math_Vector& theInfBounds,
- const math_Vector& theSupBounds,
- math_FunctionSetRoot& theSolver,
- TheIWFunction& theFunc)
-{
- const Standard_Real eps = Epsilon(1.);
- const gp_Pnt &aP3d = thePOn2S.Value();
-
- for (Standard_Integer aLIdx = 1; aLIdx <= lines.Length(); aLIdx++)
- {
- const Handle(IntSurf_LineOn2S) &aL = lines(aLIdx)->Line();
-
- if (aL->IsOutBox(aP3d))
- continue;
-
- //Look for the nearest segment
- Standard_Real aUMin = 0.0, aVMin = 0.0;
- Standard_Real aMinSqDist = RealLast();
- for (Standard_Integer aPtIdx = 1; aPtIdx < aL->NbPoints(); aPtIdx++)
- {
- const gp_Pnt &aP1 = aL->Value(aPtIdx).Value();
- const gp_Pnt &aP2 = aL->Value(aPtIdx + 1).Value();
-
- const gp_XYZ aP1P(aP3d.XYZ() - aP1.XYZ());
- const gp_XYZ aP1P2(aP2.XYZ() - aP1.XYZ());
-
- const Standard_Real aSq12 = aP1P2.SquareModulus();
-
- if (aSq12 < gp::Resolution())
- continue;
-
- const Standard_Real aDP = aP1P.Dot(aP1P2);
-
- Standard_Real aSqD = RealLast();
- if (aDP < 0.0)
- {
- continue;
- }
- else if (aDP > aSq12)
- {
- continue;
- }
- else
- {
- aSqD = aP1P.CrossSquareMagnitude(aP1P2) / aSq12;
- }
-
- if (aSqD < aMinSqDist)
- {
- aMinSqDist = aSqD;
-
- const Standard_Real aL1 = aDP / aSq12;
- const Standard_Real aL2 = 1.0 - aL1;
-
- if (aL1 < eps || aL2 < eps)
- {
- return Standard_True;
- }
-
- Standard_Real aU1, aV1, aU2, aV2;
- aL->Value(aPtIdx).ParametersOnSurface(reversed, aU1, aV1);
- aL->Value(aPtIdx + 1).ParametersOnSurface(reversed, aU2, aV2);
-
- aUMin = aL1*aU2 + aL2*aU1;
- aVMin = aL1*aV2 + aL2*aV1;
- }
- }
-
- if (aMinSqDist > Precision::Infinite())
- continue;
-
- math_Vector aVecPrms(1, 2);
- aVecPrms(1) = aUMin;
- aVecPrms(2) = aVMin;
- theSolver.Perform(theFunc, aVecPrms, theInfBounds, theSupBounds);
- if (!theSolver.IsDone())
- continue;
-
- theSolver.Root(aVecPrms);
-
- const gp_Pnt aPa(theFunc.PSurface()->Value(aUMin, aVMin)),
- aPb(theFunc.PSurface()->Value(aVecPrms(1), aVecPrms(2)));
- const Standard_Real aSqD1 = aPb.SquareDistance(aP3d);
- const Standard_Real aSqD2 = aPa.SquareDistance(aPb);
-
- if (aSqD1 < 4.0*aSqD2)
- {
- return Standard_True;
- }
- }
-
- return Standard_False;
-}