// 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 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 // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569 #include #include static void FindVertex (const TheArc&, const Handle(TheTopolTool)&, TheFunction&, IntStart_SequenceOfPathPoint&, const Standard_Real); static void BoundedArc (const TheArc& A, const Handle(TheTopolTool)& Domain, const Standard_Real Pdeb, const Standard_Real Pfin, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, IntStart_SequenceOfSegment& seg, const Standard_Real TolBoundary, const Standard_Real TolTangency, Standard_Boolean& Arcsol, const Standard_Boolean RecheckOnRegularity); static void PointProcess (const gp_Pnt&, const Standard_Real, const TheArc&, const Handle(TheTopolTool)&, IntStart_SequenceOfPathPoint&, const Standard_Real, Standard_Integer&); static Standard_Integer TreatLC (const TheArc& A, const Handle(TheTopolTool)& aDomain, const IntSurf_Quadric& aQuadric, const Standard_Real TolBoundary, IntStart_SequenceOfPathPoint& pnt); static Standard_Boolean IsRegularity(const TheArc& A, const Handle(TheTopolTool)& aDomain); //======================================================================= //function : FindVertex //purpose : //======================================================================= void FindVertex (const TheArc& A, const Handle(TheTopolTool)& Domain, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, const Standard_Real Toler) { // Find the vertex of the arc A restriction solutions. It stores // Vertex in the list solutions pnt. TheVertex vtx; Standard_Real param,valf; Standard_Integer 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 (Abs(valf) <= Toler) { itemp = Func.GetStateNumber(); pnt.Append(IntStart_ThePathPoint(Func.Valpoint(itemp),Toler, vtx,A,param)); // Solution is added } Domain->NextVertex(); } } static void BoundedArc (const TheArc& A, const Handle(TheTopolTool)& Domain, const Standard_Real Pdeb, const Standard_Real Pfin, TheFunction& Func, IntStart_SequenceOfPathPoint& pnt, IntStart_SequenceOfSegment& seg, const Standard_Real TolBoundary, const Standard_Real TolTangency, Standard_Boolean& Arcsol, const Standard_Boolean 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). Standard_Integer i,Nbi,Nbp; gp_Pnt ptdeb,ptfin; Standard_Real pardeb = 0., parfin = 0.; Standard_Integer ideb,ifin,range,ranged,rangef; // Creer l echantillonage (math_FunctionSample ou classe heritant) // Appel a math_FunctionAllRoots Standard_Real EpsX = TheArcTool::Resolution(A,Precision::Confusion()); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@ 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 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ EpsX = 0.0000000001; //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // Standard_Integer NbEchant = TheSOBTool::NbSamplesOnArc(A); Standard_Integer NbEchant = Func.NbSamples(); //-- Modif 24 Aout 93 ----------------------------- Standard_Real 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 //-------------------------------------------------- Standard_Real para=0,dist,maxdist; /* if(NbEchant<20) NbEchant = 20; //-- lbr le 22 Avril 96 //-- Toujours des pbs */ if(NbEchant<100) NbEchant = 100; //-- lbr le 22 Avril 96 //-- Toujours des pbs //-------------------------------------------------------------- REJECTIONS le 15 oct 98 Standard_Boolean Rejection=Standard_True; Standard_Real maxdr,maxr,minr,ur,dur; minr=RealLast(); maxr=-minr; maxdr=-minr; dur=(Pfin-Pdeb)*0.2; for(i=1,ur=Pdeb;i<=6;i++) { Standard_Real F,D; if(Func.Values(ur,F,D)) { Standard_Real lminr,lmaxr; if(D<0.0) D=-D; D*=dur+dur; if(D>maxdr) maxdr=D; lminr=F-D; lmaxr=F+D; if(lminrmaxr) maxr=lmaxr; if(minr<0.0 && maxr>0.0) { Rejection=Standard_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=Standard_False; } } Arcsol=Standard_False; if(Rejection==Standard_False) { math_FunctionSample Echant(Pdeb,Pfin,NbEchant); Standard_Boolean aelargir=Standard_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++) { Standard_Real u = Echant.GetParameter(i); if(Func.Value(u,dist)) { if(dist>maxdist || -dist>maxdist) { aelargir=Standard_False; } } } if(!(aelargir && maxdist<0.01)) { maxdist = TolBoundary; } math_FunctionAllRoots Sol(Func,Echant,EpsX,maxdist,maxdist); //-- TolBoundary,nTolTangency); if (!Sol.IsDone()) {Standard_Failure::Raise();} Nbp=Sol.NbPoints(); //jgv: build solution on the whole boundary if (RecheckOnRegularity && Nbp > 0 && IsRegularity(A, Domain)) { //Standard_Real theTol = Domain->MaxTolerance(A); //theTol += theTol; Standard_Real theTol = 5.e-4; math_FunctionAllRoots SolAgain(Func,Echant,EpsX,theTol,theTol); //-- TolBoundary,nTolTangency); if (!SolAgain.IsDone()) {Standard_Failure::Raise();} Standard_Integer Nbi_again = SolAgain.NbIntervals(); if (Nbi_again > 0) { Standard_Integer NbSamples = 10; Standard_Real delta = (Pfin - Pdeb)/NbSamples; Standard_Real GlobalTol = theTol*10; Standard_Boolean SolOnBoundary = Standard_True; for (i = 0; i <= NbSamples; i++) { Standard_Real aParam = Pdeb + i*delta; Standard_Real aValue; Func.Value(aParam, aValue); if (Abs(aValue) > GlobalTol) { SolOnBoundary = Standard_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 (Abs(pardeb - Pdeb) <= Precision::PConfusion()) pardeb = Pdeb; if (Abs(parfin - Pfin) <= Precision::PConfusion()) parfin = Pfin; SolAgain.GetIntervalState(i,ideb,ifin); //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : i= "<TabSol[i+1]) { ok=Standard_False; para=TabSol[i]; TabSol[i]=TabSol[i+1]; TabSol[i+1]=para; } } } while(ok==Standard_False); //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 Standard_Integer ip; const IntSurf_Quadric& aQuadric=Func.Quadric(); 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 0.001) aTol = 0.001; // fix floating point exception 569, chl-922-e9 parap1 = (Abs(parap1) < 1.e9) ? parap1 : ((parap1 >= 0.) ? 1.e9 : -1.e9); para = (Abs(para) < 1.e9) ? para : ((para >= 0.) ? 1.e9 : -1.e9); Standard_Integer aNbNodes = RealToInt(Ceiling((parap1 - para)/aTol)); Standard_Real aVal = RealLast(); //Standard_Integer aNbNodes = 23; Standard_Real aDelta = (parap1 - para)/(aNbNodes + 1.); Standard_Integer ii; Standard_Real aCurPar; Standard_Real aCurVal; for (ii = 0; ii <= aNbNodes + 1; ii++) { aCurPar = (ii < aNbNodes + 1) ? para + ii*aDelta : parap1; if (Func.Value(aCurPar, aCurVal)) { //if (aCurVal < aVal) { if (Abs(aCurVal) < aVal) { //aVal = aCurVal; aVal = Abs(aCurVal); param = aCurPar; } } } // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569 End TabSol[i]=Pdeb-1; TabSol[i+1]=param; } } } for (i=1; i<=Nbp; i++) { para=TabSol[i]; if((para-Pdeb)0 0 <- Nbi "<U0) { Umin=U0-10.0; } if(UmaxInitialize(A); Domain->InitVertexIterator(); found = Standard_False; goon = Domain->MoreVertex(); while (goon) { vtx = Domain->Vertex(); dist= Abs(Para-TheSOBTool::Parameter(vtx,A)); toler = TheSOBTool::Tolerance(vtx,A); #ifdef DEB if(toler>0.1) { cout<<"IntStart_SearchOnBoundaries_1.gxx : ** WARNING ** Tol Vertex="<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 && Abs(ptsol.Parameter()-Para) <= toler) { found=Standard_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 = Standard_True; goon = Standard_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 Standard_Boolean found_internal = Standard_False; for (k = 1; k <= pnt.Length(); k++) { ptsol = pnt.Value(k); if (ptsol.Arc() != A || !ptsol.IsNew()) //vertex continue; if (Abs(ptsol.Parameter()-Para) <= Precision::PConfusion()) { found_internal = Standard_True; Range = k; } } ///////////////////////////////////////////////////////////// if (!found_internal) { Standard_Real TOL=Tol; TOL*=1000.0; if(TOL>0.001) TOL=0.001; ptsol.SetValue(Pt,TOL,A,Para); pnt.Append(ptsol); Range = pnt.Length(); } } } //======================================================================= //function : IsRegularity //purpose : //======================================================================= Standard_Boolean IsRegularity(const TheArc& /*A*/, const Handle(TheTopolTool)& aDomain) { Standard_Address anEAddress=aDomain->Edge(); if (anEAddress==NULL) { return Standard_False; } TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress; return (BRep_Tool::HasContinuity(*anE)); } //======================================================================= //function : TreatLC //purpose : //======================================================================= Standard_Integer TreatLC (const TheArc& A, const Handle(TheTopolTool)& aDomain, const IntSurf_Quadric& aQuadric, const Standard_Real TolBoundary, IntStart_SequenceOfPathPoint& pnt) { Standard_Integer anExitCode=1, aNbExt; Standard_Address anEAddress=aDomain->Edge(); if (anEAddress==NULL) { 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; } Standard_Real f, l, U1f, U1l, U2f, U2l, UEgde, TOL, aDist, aR, aRRel, Tol; Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, f, l); gp_Cylinder aCyl=aQuadric.Cylinder(); const gp_Ax1& anAx1=aCyl.Axis(); gp_Lin aLin(anAx1); Handle(Geom_Line) 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; } //======================================================================= //function : IntStart_SearchOnBoundaries::IntStart_SearchOnBoundaries //purpose : //======================================================================= IntStart_SearchOnBoundaries::IntStart_SearchOnBoundaries () : done(Standard_False) { } //======================================================================= //function : Perform //purpose : //======================================================================= void IntStart_SearchOnBoundaries::Perform (TheFunction& Func, const Handle(TheTopolTool)& Domain, const Standard_Real TolBoundary, const Standard_Real TolTangency, const Standard_Boolean RecheckOnRegularity) { done = Standard_False; spnt.Clear(); sseg.Clear(); Standard_Boolean Arcsol; Standard_Real PDeb,PFin, prm, tol; Standard_Integer i, nbknown, nbfound,index; gp_Pnt pt; Domain->Init(); if (Domain->More()) { all = Standard_True; } else { all = Standard_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)) { Standard_Integer 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),Standard_True); } if (TheSOBTool::HasLastPoint(A,i,index)) { newseg.SetLimitPoint(spnt.Value(nbfound+index),Standard_False); } sseg.Append(newseg); } all = (all& TheSOBTool::IsAllSolution(A)); } Domain->Next(); } done = Standard_True; }