// 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include #include #include // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569 #include #include #include #include #include #include #ifdef OCCT_DEBUG #include #include #include #include #include #include #include #endif static bool IsDegenerated(const occ::handle& theCurve); static bool IsDegenerated(const IntSurf_Quadric& theQuadric); static void FindVertex(const TheArc&, const occ::handle&, TheFunction&, IntStart_SequenceOfPathPoint&, const double); static void BoundedArc(const TheArc& A, const occ::handle& Domain, const double Pdeb, const double Pfin, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, IntStart_SequenceOfSegment& seg, const double TolBoundary, const double TolTangency, bool& Arcsol, const bool RecheckOnRegularity); static void PointProcess(const gp_Pnt&, const double, const TheArc&, const occ::handle&, IntStart_SequenceOfPathPoint&, const double, int&); static int TreatLC(const TheArc& A, const occ::handle& aDomain, const IntSurf_Quadric& aQuadric, const double TolBoundary, IntStart_SequenceOfPathPoint& pnt); static bool IsRegularity(const TheArc& A, const occ::handle& aDomain); class MinFunction : public math_Function { public: MinFunction(TheFunction& theFunc) : myFunc(&theFunc) {}; // returns value of the one-dimension-function when parameter // is equal to theX virtual bool Value(const double theX, double& theFVal) { if (!myFunc->Value(theX, theFVal)) return false; theFVal *= theFVal; return true; } // see analogical method for abstract owner class math_Function virtual int GetStateNumber() { return 0; } private: TheFunction* myFunc; }; //================================================================================================= void FindVertex(const TheArc& A, const occ::handle& Domain, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, const double Toler) { // Find the vertex of the arc A restriction solutions. It stores // Vertex in the list solutions pnt. TheVertex vtx; double param, valf; int itemp; Domain->Initialize(A); Domain->InitVertexIterator(); while (Domain->MoreVertex()) { vtx = Domain->Vertex(); param = TheSOBTool::Parameter(vtx, A); // Evaluate the function and look compared to tolerance of the // Vertex. If distance <= tolerance then add a vertex to the list of solutions. // The arc is already assumed in the load function. Func.Value(param, valf); if (std::abs(valf) <= Toler) { itemp = Func.GetStateNumber(); pnt.Append(IntStart_ThePathPoint(Func.Valpoint(itemp), Toler, vtx, A, param)); // Solution is added } Domain->NextVertex(); } } bool IsDegenerated(const occ::handle& theCurve) { if (theCurve->GetType() == GeomAbs_Circle) { gp_Circ aCirc = theCurve->Circle(); if (aCirc.Radius() <= Precision::Confusion()) return true; } return false; } bool IsDegenerated(const IntSurf_Quadric& theQuadric) { GeomAbs_SurfaceType TypeQuad = theQuadric.TypeQuadric(); if (TypeQuad == GeomAbs_Cone) { gp_Cone aCone = theQuadric.Cone(); double aSemiAngle = std::abs(aCone.SemiAngle()); if (aSemiAngle < 0.02 || aSemiAngle > 1.55) return true; } return false; } class SolInfo { public: SolInfo() : myMathIndex(-1), myValue(RealLast()) { } void Init(const math_FunctionAllRoots& theSolution, const int theIndex) { myMathIndex = theIndex; myValue = theSolution.GetPoint(theIndex); } void Init(const IntCurveSurface_HInter& theSolution, const int theIndex) { myMathIndex = theIndex; myValue = theSolution.Point(theIndex).W(); } double Value() const { return myValue; } int Index() const { return myMathIndex; } bool operator>(const SolInfo& theOther) const { return myValue > theOther.myValue; } bool operator<(const SolInfo& theOther) const { return myValue < theOther.myValue; } bool operator==(const SolInfo& theOther) const { return myValue == theOther.myValue; } double& ChangeValue() { return myValue; } private: int myMathIndex; double myValue; }; static void BoundedArc(const TheArc& A, const occ::handle& Domain, const double Pdeb, const double Pfin, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, IntStart_SequenceOfSegment& seg, const double TolBoundary, const double TolTangency, bool& Arcsol, const bool RecheckOnRegularity) { // Recherche des points solutions et des bouts d arc solution sur un arc donne. // On utilise la fonction math_FunctionAllRoots. Ne convient donc que pour // des arcs ayant un point debut et un point de fin (intervalle ferme de // parametrage). int i, Nbi = 0, Nbp = 0; gp_Pnt ptdeb, ptfin; double pardeb = 0., parfin = 0.; int ideb, ifin, range, ranged, rangef; // Creer l echantillonage (math_FunctionSample ou classe heritant) // Appel a math_FunctionAllRoots //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@ La Tolerance est asociee a l arc ( Incoherence avec le cheminement ) //@@@ ( EpsX ~ 1e-5 et ResolutionU et V ~ 1e-9 ) //@@@ le vertex trouve ici n'est pas retrouve comme point d arret d une //@@@ ligne de cheminement //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ double EpsX = 1.e-10; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // int NbEchant = TheSOBTool::NbSamplesOnArc(A); int NbEchant = Func.NbSamples(); if (NbEchant < 100) NbEchant = 100; //-- lbr le 22 Avril 96 //-- Toujours des pbs //-- Modif 24 Aout 93 ----------------------------- double nTolTangency = TolTangency; if ((Pfin - Pdeb) < (TolTangency * 10.0)) { nTolTangency = (Pfin - Pdeb) * 0.1; } if (EpsX > (nTolTangency + nTolTangency)) { EpsX = nTolTangency * 0.1; } //-------------------------------------------------- //-- Plante avec un edge avec 2 Samples //-- dont les extremites son solutions (f=0) //-- et ou la derivee est nulle //-- Exemple : un segment diametre d une sphere //-- if(NbEchant<3) NbEchant = 3; //-- lbr le 19 Avril 95 //-------------------------------------------------- double para = 0, dist, maxdist; //-------------------------------------------------------------- REJECTIONS le 15 oct 98 bool Rejection = true; double maxdr, maxr, minr, ur, dur; minr = RealLast(); maxr = -minr; maxdr = -minr; dur = (Pfin - Pdeb) * 0.2; for (i = 1, ur = Pdeb; i <= 6; i++) { double F, D; if (Func.Values(ur, F, D)) { double lminr, lmaxr; if (D < 0.0) D = -D; D *= dur + dur; if (D > maxdr) maxdr = D; lminr = F - D; lmaxr = F + D; if (lminr < minr) minr = lminr; if (lmaxr > maxr) maxr = lmaxr; if (minr < 0.0 && maxr > 0.0) { Rejection = false; break; } } ur += dur; } if (Rejection) { dur = 0.001 + maxdr + (maxr - minr) * 0.1; minr -= dur; maxr += dur; if (minr < 0.0 && maxr > 0.0) { Rejection = false; } } Arcsol = false; if (Rejection == false) { const IntSurf_Quadric& aQuadric = Func.Quadric(); GeomAbs_SurfaceType TypeQuad = aQuadric.TypeQuadric(); GeomAbs_CurveType TypeConS = GeomAbs_OtherCurve; IntCurveSurface_HInter IntCS; bool IsIntCSdone = false; NCollection_Sequence Params; std::unique_ptr pSol; math_FunctionSample Echant(Pdeb, Pfin, NbEchant); bool aelargir = true; // modified by NIZNHY-PKV Thu Apr 12 09:25:19 2001 f // // maxdist = 100.0*TolBoundary; maxdist = TolBoundary + TolTangency; // // modified by NIZNHY-PKV Thu Apr 12 09:25:23 2001 t for (i = 1; i <= NbEchant && aelargir; i++) { double u = Echant.GetParameter(i); if (Func.Value(u, dist)) { if (dist > maxdist || -dist > maxdist) { aelargir = false; } } } if (!(aelargir && maxdist < 0.01)) { maxdist = TolBoundary; } if (TypeQuad != GeomAbs_OtherSurface) // intersection of boundary curve and quadric surface { // Exact solution occ::handle aSurf = Func.Surface(); Adaptor3d_CurveOnSurface ConS(A, aSurf); TypeConS = ConS.GetType(); #ifdef OCCT_DEBUG occ::handle CurveConS; switch (TypeConS) { case GeomAbs_Line: { CurveConS = new Geom_Line(ConS.Line()); break; } case GeomAbs_Circle: { CurveConS = new Geom_Circle(ConS.Circle()); break; } case GeomAbs_Ellipse: { CurveConS = new Geom_Ellipse(ConS.Ellipse()); break; } case GeomAbs_Hyperbola: { CurveConS = new Geom_Hyperbola(ConS.Hyperbola()); break; } case GeomAbs_Parabola: { CurveConS = new Geom_Parabola(ConS.Parabola()); break; } case GeomAbs_BezierCurve: { CurveConS = ConS.Bezier(); break; } case GeomAbs_BSplineCurve: { CurveConS = ConS.BSpline(); break; } default: { double MaxDeviation, AverageDeviation; GeomLib::BuildCurve3d(1.e-5, ConS, ConS.FirstParameter(), ConS.LastParameter(), CurveConS, MaxDeviation, AverageDeviation); break; } } #endif occ::handle HConS = new Adaptor3d_CurveOnSurface(ConS); occ::handle QuadSurf; switch (TypeQuad) { case GeomAbs_Plane: { QuadSurf = new Geom_Plane(aQuadric.Plane()); break; } case GeomAbs_Cylinder: { QuadSurf = new Geom_CylindricalSurface(aQuadric.Cylinder()); break; } case GeomAbs_Cone: { QuadSurf = new Geom_ConicalSurface(aQuadric.Cone()); break; } case GeomAbs_Sphere: { QuadSurf = new Geom_SphericalSurface(aQuadric.Sphere()); break; } case GeomAbs_Torus: { QuadSurf = new Geom_ToroidalSurface(aQuadric.Torus()); break; } default: break; } occ::handle GAHsurf = new GeomAdaptor_Surface(QuadSurf); if ((TypeConS == GeomAbs_Line || TypeConS == GeomAbs_Circle || TypeConS == GeomAbs_Ellipse || TypeConS == GeomAbs_Parabola || TypeConS == GeomAbs_Hyperbola) && TypeQuad != GeomAbs_Torus && !IsDegenerated(HConS) && !IsDegenerated(aQuadric)) { // exact intersection for only canonic curves and real quadric surfaces IntCS.Perform(HConS, GAHsurf); } IsIntCSdone = IntCS.IsDone(); if (IsIntCSdone) { Nbp = IntCS.NbPoints(); Nbi = IntCS.NbSegments(); } // If we have not got intersection, it may be touch with some tolerance, // need to be checked if (Nbp == 0 && Nbi == 0) IsIntCSdone = false; } // if (TypeQuad != GeomAbs_OtherSurface) - intersection of boundary curve and quadric surface if (!IsIntCSdone) { pSol.reset(new math_FunctionAllRoots(Func, Echant, EpsX, maxdist, maxdist)); //-- TolBoundary,nTolTangency); if (!pSol->IsDone()) { throw Standard_Failure(); } Nbp = pSol->NbPoints(); } // // jgv: build solution on the whole boundary if (RecheckOnRegularity && Nbp > 0 && IsRegularity(A, Domain)) { // double theTol = Domain->MaxTolerance(A); // theTol += theTol; double theTol = 5.e-4; math_FunctionAllRoots SolAgain(Func, Echant, EpsX, theTol, theTol); //-- TolBoundary,nTolTangency); if (!SolAgain.IsDone()) { throw Standard_Failure(); } int Nbi_again = SolAgain.NbIntervals(); if (Nbi_again > 0) { int NbSamples = 10; double delta = (Pfin - Pdeb) / NbSamples; double GlobalTol = theTol * 10; bool SolOnBoundary = true; for (i = 0; i <= NbSamples; i++) { double aParam = Pdeb + i * delta; double aValue; Func.Value(aParam, aValue); if (std::abs(aValue) > GlobalTol) { SolOnBoundary = false; break; } } if (SolOnBoundary) { for (i = 1; i <= Nbi_again; i++) { IntStart_TheSegment newseg; newseg.SetValue(A); // Recuperer point debut et fin, et leur parametre. SolAgain.GetInterval(i, pardeb, parfin); if (std::abs(pardeb - Pdeb) <= Precision::PConfusion()) pardeb = Pdeb; if (std::abs(parfin - Pfin) <= Precision::PConfusion()) parfin = Pfin; SolAgain.GetIntervalState(i, ideb, ifin); //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : i= "< 0 && IsRegularity(A, Domain)) //////////////////////////////////////////// //-- detection du cas ou la fonction est quasi tangente et que les //-- zeros sont quasi confondus. //-- Dans ce cas on prend le point "milieu" //-- On suppose que les solutions sont triees. if (Nbp) { NCollection_Array1 aSI(1, Nbp); for (i = 1; i <= Nbp; i++) { if (IsIntCSdone) aSI(i).Init(IntCS, i); else aSI(i).Init(*pSol, i); } std::sort(aSI.begin(), aSI.end()); // modified by NIZNHY-PKV Wed Mar 21 18:34:18 2001 f ////////////////////////////////////////////////////////// // The treatment of the situation when line(arc) that is // tangent to cylinder(domain). // We should have only one solution i.e Nbp=1. Ok? // But we have 2,3,.. solutions. That is wrong ersult. // The TreatLC(...) function is dedicated to solve the pb. // PKV Fri Mar 23 12:17:29 2001 int ip = TreatLC(A, Domain, aQuadric, TolBoundary, pnt); if (ip) { ////////////////////////////////////////////////////////// // modified by NIZNHY-PKV Wed Mar 21 18:34:23 2001 t // // Using of old usual way proposed by Laurent // for (i = 1; i < Nbp; i++) { double parap1 = aSI(i + 1).Value(); para = aSI(i).Value(); double param = (para + parap1) * 0.5; double yf = 0.0; double ym = 0.0; double yl = 0.0; if (Func.Value(param, ym) && std::abs(ym) < maxdist) { double sm = std::copysign(1., ym); bool aTang = Func.Value(para, yf) && Func.Value(parap1, yl); if (aTang) { // Line can be tangent surface if all distances less then maxdist aTang = aTang && std::abs(yf) < maxdist && std::abs(yl) < maxdist; } if (aTang && IsIntCSdone && TypeConS == GeomAbs_Line) { // Interval is got by exact intersection // Line can be tangent if all points are on the same side of surface // it means that signs of all distances are the same double sf = std::copysign(1., yf), sl = std::copysign(1., yl); aTang = aTang && (sm == sf) && (sm == sl); } if (aTang) { // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569 Begin // Consider this interval as tangent one. Treat it to find // parameter with the lowest function value. // Compute the number of nodes. double aTol = TolBoundary * 1000.0; if (aTol > 0.001) aTol = 0.001; // fix floating point exception 569, chl-922-e9 parap1 = (std::abs(parap1) < 1.e9) ? parap1 : ((parap1 >= 0.) ? 1.e9 : -1.e9); para = (std::abs(para) < 1.e9) ? para : ((para >= 0.) ? 1.e9 : -1.e9); int aNbNodes = RealToInt(std::ceil((parap1 - para) / aTol)); double aVal = RealLast(); double aValMax = 0.; // int aNbNodes = 23; double aDelta = (parap1 - para) / (aNbNodes + 1.); int ii; double aCurPar; double aCurVal; for (ii = 0; ii <= aNbNodes + 1; ii++) { aCurPar = (ii < aNbNodes + 1) ? para + ii * aDelta : parap1; if (Func.Value(aCurPar, aCurVal)) { double anAbsVal = std::abs(aCurVal); if (anAbsVal < aVal) { aVal = anAbsVal; param = aCurPar; } if (anAbsVal > aValMax) { aValMax = anAbsVal; } } } // At last, interval got by exact intersection can be considered as tangent if // minimal distance is inside interval and // minimal and maximal values are almost the same if (IsIntCSdone && aNbNodes > 1) { aTang = std::abs(param - para) > EpsX && std::abs(parap1 - param) > EpsX && 0.01 * aValMax <= aVal; } if (aTang) { aSI(i).ChangeValue() = Pdeb - 1; aSI(i + 1).ChangeValue() = param; } } } } for (i = 1; i <= Nbp; i++) { para = aSI(i).Value(); if ((para - Pdeb) < EpsX || (Pfin - para) < EpsX) continue; if (!Func.Value(para, dist)) continue; dist = std::abs(dist); int anIndx = -1; // const double aParam = Sol->GetPoint(aSI(i).Index()); const double aParam = aSI(i).Value(); if (dist < maxdist) { if (!IsIntCSdone && (std::abs(aParam - Pdeb) <= Precision::PConfusion() || std::abs(aParam - Pfin) <= Precision::PConfusion())) { anIndx = pSol->GetPointState(aSI(i).Index()); } } gp_Pnt aPnt(anIndx < 0 ? Func.LastComputedPoint() : Func.Valpoint(anIndx)); if (dist > 0.1 * Precision::Confusion()) { // Precise found points. It results in following: // 1. Make the vertex nearer to the intersection line // (see description to issue #27252 in order to // understand necessity). // 2. Merge two near vertices to single point. // All members in TabSol array has already been sorted in increase order. // Now, we limit precise boundaries in order to avoid changing this order. const double aFPar = (i == 1) ? Pdeb : (para + aSI(i - 1).Value()) / 2.0; const double aLPar = (i == Nbp) ? Pfin : (para + aSI(i + 1).Value()) / 2.0; MinFunction aNewFunc(Func); math_BrentMinimum aMin(Precision::Confusion()); aMin.Perform(aNewFunc, aFPar, para, aLPar); if (aMin.IsDone()) { para = aMin.Location(); const gp_Pnt2d aP2d(A->Value(para)); aPnt = Func.Surface()->Value(aP2d.X(), aP2d.Y()); } } PointProcess(aPnt, para, A, Domain, pnt, TolBoundary, range); } } // end of if(ip) } // end of if(Nbp) // Pour chaque intervalle trouve faire // Traiter les extremites comme des points // Ajouter intervalle dans la liste des segments if (!IsIntCSdone) Nbi = pSol->NbIntervals(); if (!RecheckOnRegularity && Nbp) { //--cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx :Nbp>0 0 <- Nbi "<GetInterval(i, pardeb, parfin); pSol->GetIntervalState(i, ideb, ifin); //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : i= "< U0) { Umin = U0 - 10.0; } if (Umax < U0) { Umax = U0 + 10.0; } PFin = Umax + 10. * (Umax - Umin); PDeb = Umin - 10. * (Umax - Umin); } else { //-- Possibilite de Arc totalement inclu ds Quad PDeb = 1e10; PFin = -1e10; } } //================================================================================================= void PointProcess(const gp_Pnt& Pt, const double Para, const TheArc& A, const occ::handle& Domain, IntStart_SequenceOfPathPoint& pnt, const double Tol, int& Range) { // Check to see if a solution point is coincident with a vertex. // If confused, you should find this vertex in the list of // Start. It then returns the position of this point in the list pnt. // Otherwise, add the point in the list. int k; bool found, goon; double dist, toler; int Nbsol = pnt.Length(); TheVertex vtx; IntStart_ThePathPoint ptsol; Domain->Initialize(A); Domain->InitVertexIterator(); found = false; goon = Domain->MoreVertex(); while (goon) { vtx = Domain->Vertex(); dist = std::abs(Para - TheSOBTool::Parameter(vtx, A)); toler = TheSOBTool::Tolerance(vtx, A); #ifdef OCCT_DEBUG if (toler > 0.1) { std::cout << "IntStart_SearchOnBoundaries_1.gxx : ** WARNING ** Tol Vertex=" << toler << std::endl; std::cout << " Ou Edge degenere Ou Kro pointu" << std::endl; if (toler > 10000) toler = 1e-7; } #endif if (dist <= toler) { // Locate the vertex in the list of solutions k = 1; found = (k > Nbsol); while (!found) { ptsol = pnt.Value(k); if (!ptsol.IsNew()) { // jag 940608 if (ptsol.Vertex() == vtx && ptsol.Arc() == A) { if (Domain->Identical(ptsol.Vertex(), vtx) && ptsol.Arc() == A && std::abs(ptsol.Parameter() - Para) <= toler) { found = true; } else { k = k + 1; found = (k > Nbsol); } } else { k = k + 1; found = (k > Nbsol); } } if (k <= Nbsol) { // We find the vertex Range = k; } else { // Otherwise ptsol.SetValue(Pt, Tol, vtx, A, Para); pnt.Append(ptsol); Range = pnt.Length(); } found = true; goon = false; } else { Domain->NextVertex(); goon = Domain->MoreVertex(); } } if (!found) { // No one is falling on a vertex // jgv: do not add segment's extremities if they already exist bool found_internal = false; for (k = 1; k <= pnt.Length(); k++) { ptsol = pnt.Value(k); if (ptsol.Arc() != A || !ptsol.IsNew()) // vertex continue; if (std::abs(ptsol.Parameter() - Para) <= Precision::PConfusion()) { found_internal = true; Range = k; } } ///////////////////////////////////////////////////////////// if (!found_internal) { double TOL = Tol; TOL *= 1000.0; // if(TOL>0.001) TOL=0.001; if (TOL > 0.005) TOL = 0.005; // #24643 ptsol.SetValue(Pt, TOL, A, Para); pnt.Append(ptsol); Range = pnt.Length(); } } } //================================================================================================= bool IsRegularity(const TheArc& /*A*/, const occ::handle& aDomain) { void* anEAddress = aDomain->Edge(); if (anEAddress == nullptr) { return false; } TopoDS_Edge* anE = (TopoDS_Edge*)anEAddress; return (BRep_Tool::HasContinuity(*anE)); } //================================================================================================= int TreatLC(const TheArc& A, const occ::handle& aDomain, const IntSurf_Quadric& aQuadric, const double TolBoundary, IntStart_SequenceOfPathPoint& pnt) { int anExitCode = 1, aNbExt; void* anEAddress = aDomain->Edge(); if (anEAddress == nullptr) { return anExitCode; } TopoDS_Edge* anE = (TopoDS_Edge*)anEAddress; if (BRep_Tool::Degenerated(*anE)) { return anExitCode; } GeomAbs_CurveType aTypeE; BRepAdaptor_Curve aBAC(*anE); aTypeE = aBAC.GetType(); if (aTypeE != GeomAbs_Line) { return anExitCode; } GeomAbs_SurfaceType aTypeS; aTypeS = aQuadric.TypeQuadric(); if (aTypeS != GeomAbs_Cylinder) { return anExitCode; } double f, l, U1f, U1l, U2f, U2l, UEgde, TOL, aDist, aR, aRRel, Tol; occ::handle aCEdge = BRep_Tool::Curve(*anE, f, l); gp_Cylinder aCyl = aQuadric.Cylinder(); const gp_Ax1& anAx1 = aCyl.Axis(); gp_Lin aLin(anAx1); occ::handle aCAxis = new Geom_Line(aLin); aR = aCyl.Radius(); U1f = aCAxis->FirstParameter(); U1l = aCAxis->LastParameter(); U2f = aCEdge->FirstParameter(); U2l = aCEdge->LastParameter(); GeomAdaptor_Curve C1, C2; C1.Load(aCAxis); C2.Load(aCEdge); Tol = Precision::PConfusion(); Extrema_ExtCC anExtCC(C1, C2, U1f, U1l, U2f, U2l, Tol, Tol); aNbExt = anExtCC.NbExt(); if (aNbExt != 1) { return anExitCode; } gp_Pnt P1, PEdge; Extrema_POnCurv PC1, PC2; anExtCC.Points(1, PC1, PC2); P1 = PC1.Value(); PEdge = PC2.Value(); UEgde = PC2.Parameter(); aDist = PEdge.Distance(P1); aRRel = fabs(aDist - aR) / aR; if (aRRel > TolBoundary) { return anExitCode; } if (UEgde < (f + TolBoundary) || UEgde > (l - TolBoundary)) { return anExitCode; } // // Do not wonder ! // It was done as into PointProcess(...) function // printf("TreatLC()=> tangent line is found\n"); TOL = 1000. * TolBoundary; if (TOL > 0.001) TOL = 0.001; IntStart_ThePathPoint ptsol; ptsol.SetValue(PEdge, TOL, A, UEgde); pnt.Append(ptsol); anExitCode = 0; return anExitCode; } //================================================================================================= IntStart_SearchOnBoundaries::IntStart_SearchOnBoundaries() : done(false), all(false) { } //================================================================================================= void IntStart_SearchOnBoundaries::Perform(TheFunction& Func, const occ::handle& Domain, const double TolBoundary, const double TolTangency, const bool RecheckOnRegularity) { done = false; spnt.Clear(); sseg.Clear(); bool Arcsol; double PDeb, PFin, prm, tol; int i, nbknown, nbfound, index; gp_Pnt pt; Domain->Init(); if (Domain->More()) { all = true; } else { all = false; } while (Domain->More()) { TheArc A = Domain->Value(); if (!TheSOBTool::HasBeenSeen(A)) { Func.Set(A); FindVertex(A, Domain, Func, spnt, TolBoundary); TheSOBTool::Bounds(A, PDeb, PFin); if (Precision::IsNegativeInfinite(PDeb) || Precision::IsPositiveInfinite(PFin)) { int NbEchant; ComputeBoundsfromInfinite(Func, PDeb, PFin, NbEchant); } BoundedArc(A, Domain, PDeb, PFin, Func, spnt, sseg, TolBoundary, TolTangency, Arcsol, RecheckOnRegularity); all = (all && Arcsol); } else { // as it seems we'll never be here, because // TheSOBTool::HasBeenSeen(A) always returns FALSE nbfound = spnt.Length(); // On recupere les points connus nbknown = TheSOBTool::NbPoints(A); for (i = 1; i <= nbknown; i++) { TheSOBTool::Value(A, i, pt, tol, prm); if (TheSOBTool::IsVertex(A, i)) { TheVertex vtx; TheSOBTool::Vertex(A, i, vtx); spnt.Append(IntStart_ThePathPoint(pt, tol, vtx, A, prm)); } else { spnt.Append(IntStart_ThePathPoint(pt, tol, A, prm)); } } // On recupere les arcs solutions nbknown = TheSOBTool::NbSegments(A); for (i = 1; i <= nbknown; i++) { IntStart_TheSegment newseg; newseg.SetValue(A); if (TheSOBTool::HasFirstPoint(A, i, index)) { newseg.SetLimitPoint(spnt.Value(nbfound + index), true); } if (TheSOBTool::HasLastPoint(A, i, index)) { newseg.SetLimitPoint(spnt.Value(nbfound + index), false); } sseg.Append(newseg); } all = (all & TheSOBTool::IsAllSolution(A)); } Domain->Next(); } done = true; }