Warning, /include/opencascade/IntStart_SearchOnBoundaries.gxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014
0015 #include <algorithm>
0016 #include <memory>
0017 #include <TopoDS_Edge.hxx>
0018 #include <Geom_Curve.hxx>
0019 #include <BRepAdaptor_Curve.hxx>
0020 #include <Adaptor3d_Surface.hxx>
0021 #include <Adaptor3d_CurveOnSurface.hxx>
0022 #include <Adaptor3d_CurveOnSurface.hxx>
0023 #include <GeomAbs_SurfaceType.hxx>
0024 #include <BRep_Tool.hxx>
0025 #include <Geom_Line.hxx>
0026 #include <Geom_Plane.hxx>
0027 #include <Geom_CylindricalSurface.hxx>
0028 #include <Geom_ConicalSurface.hxx>
0029 #include <Geom_SphericalSurface.hxx>
0030 #include <Geom_ToroidalSurface.hxx>
0031 #include <gp_Lin.hxx>
0032 #include <gp_Vec.hxx>
0033 #include <gp_Dir.hxx>
0034 #include <gp_Cylinder.hxx>
0035 #include <gp_Ax1.hxx>
0036 #include <gp_Lin.hxx>
0037
0038 #include <GeomAdaptor_Curve.hxx>
0039 #include <GeomAdaptor_Surface.hxx>
0040 #include <Precision.hxx>
0041 #include <Extrema_ExtCC.hxx>
0042 //#include <Extrema_ExtCS.hxx>
0043 #include <Extrema_POnCurv.hxx>
0044 #include <IntCurveSurface_HInter.hxx>
0045
0046 #include <math_FunctionSample.hxx>
0047 #include <math_FunctionAllRoots.hxx>
0048 #include <TColgp_SequenceOfPnt.hxx>
0049
0050 // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569
0051
0052 #include <Precision.hxx>
0053 #include <IntSurf_Quadric.hxx>
0054 #include <math_Function.hxx>
0055 #include <math_BrentMinimum.hxx>
0056 #include <math_Matrix.hxx>
0057 #include <math_Vector.hxx>
0058 #include <NCollection_Array1.hxx>
0059
0060 #ifdef OCCT_DEBUG
0061 #include <Geom_Circle.hxx>
0062 #include <Geom_Ellipse.hxx>
0063 #include <Geom_Hyperbola.hxx>
0064 #include <Geom_Parabola.hxx>
0065 #include <Geom_BezierCurve.hxx>
0066 #include <Geom_BSplineCurve.hxx>
0067 #include <GeomLib.hxx>
0068 #endif
0069
0070
0071 static Standard_Boolean IsDegenerated(const Handle(Adaptor3d_CurveOnSurface)& theCurve);
0072 static Standard_Boolean IsDegenerated(const IntSurf_Quadric& theQuadric);
0073
0074 static void FindVertex (const TheArc&,
0075 const Handle(TheTopolTool)&,
0076 TheFunction&,
0077 IntStart_SequenceOfPathPoint&,
0078 const Standard_Real);
0079
0080
0081 static void BoundedArc (const TheArc& A,
0082 const Handle(TheTopolTool)& Domain,
0083 const Standard_Real Pdeb,
0084 const Standard_Real Pfin,
0085 TheFunction& Func,
0086 IntStart_SequenceOfPathPoint& pnt,
0087 IntStart_SequenceOfSegment& seg,
0088 const Standard_Real TolBoundary,
0089 const Standard_Real TolTangency,
0090 Standard_Boolean& Arcsol,
0091 const Standard_Boolean RecheckOnRegularity);
0092
0093 static void PointProcess (const gp_Pnt&,
0094 const Standard_Real,
0095 const TheArc&,
0096 const Handle(TheTopolTool)&,
0097 IntStart_SequenceOfPathPoint&,
0098 const Standard_Real,
0099 Standard_Integer&);
0100
0101 static Standard_Integer TreatLC (const TheArc& A,
0102 const Handle(TheTopolTool)& aDomain,
0103 const IntSurf_Quadric& aQuadric,
0104 const Standard_Real TolBoundary,
0105 IntStart_SequenceOfPathPoint& pnt);
0106
0107 static Standard_Boolean IsRegularity(const TheArc& A,
0108 const Handle(TheTopolTool)& aDomain);
0109
0110 class MinFunction : public math_Function
0111 {
0112 public:
0113 MinFunction(TheFunction &theFunc) : myFunc(&theFunc) {};
0114
0115 //returns value of the one-dimension-function when parameter
0116 //is equal to theX
0117 virtual Standard_Boolean Value(const Standard_Real theX,
0118 Standard_Real& theFVal)
0119 {
0120 if(!myFunc->Value(theX, theFVal))
0121 return Standard_False;
0122
0123 theFVal *= theFVal;
0124 return Standard_True;
0125 }
0126
0127 //see analogical method for abstract owner class math_Function
0128 virtual Standard_Integer GetStateNumber()
0129 {
0130 return 0;
0131 }
0132
0133 private:
0134 TheFunction *myFunc;
0135 };
0136
0137
0138 //=======================================================================
0139 //function : FindVertex
0140 //purpose :
0141 //=======================================================================
0142 void FindVertex (const TheArc& A,
0143 const Handle(TheTopolTool)& Domain,
0144 TheFunction& Func,
0145 IntStart_SequenceOfPathPoint& pnt,
0146 const Standard_Real Toler)
0147 {
0148
0149 // Find the vertex of the arc A restriction solutions. It stores
0150 // Vertex in the list solutions pnt.
0151
0152
0153 TheVertex vtx;
0154 Standard_Real param,valf;
0155 Standard_Integer itemp;
0156
0157 Domain->Initialize(A);
0158 Domain->InitVertexIterator();
0159 while (Domain->MoreVertex()) {
0160 vtx = Domain->Vertex();
0161 param = TheSOBTool::Parameter(vtx,A);
0162
0163 // Evaluate the function and look compared to tolerance of the
0164 // Vertex. If distance <= tolerance then add a vertex to the list of solutions.
0165 // The arc is already assumed in the load function.
0166
0167 Func.Value(param,valf);
0168 if (Abs(valf) <= Toler) {
0169 itemp = Func.GetStateNumber();
0170 pnt.Append(IntStart_ThePathPoint(Func.Valpoint(itemp),Toler, vtx,A,param));
0171 // Solution is added
0172 }
0173 Domain->NextVertex();
0174 }
0175 }
0176
0177 Standard_Boolean IsDegenerated(const Handle(Adaptor3d_CurveOnSurface)& theCurve)
0178 {
0179 if (theCurve->GetType() == GeomAbs_Circle)
0180 {
0181 gp_Circ aCirc = theCurve->Circle();
0182 if (aCirc.Radius() <= Precision::Confusion())
0183 return Standard_True;
0184 }
0185 return Standard_False;
0186 }
0187
0188 Standard_Boolean IsDegenerated(const IntSurf_Quadric& theQuadric)
0189 {
0190 GeomAbs_SurfaceType TypeQuad = theQuadric.TypeQuadric();
0191 if (TypeQuad == GeomAbs_Cone)
0192 {
0193 gp_Cone aCone = theQuadric.Cone();
0194 Standard_Real aSemiAngle = Abs(aCone.SemiAngle());
0195 if (aSemiAngle < 0.02 || aSemiAngle > 1.55)
0196 return Standard_True;
0197 }
0198 return Standard_False;
0199 }
0200
0201 class SolInfo
0202 {
0203 public:
0204 SolInfo() : myMathIndex(-1), myValue(RealLast())
0205 {
0206 }
0207
0208 void Init(const math_FunctionAllRoots& theSolution, const Standard_Integer theIndex)
0209 {
0210 myMathIndex = theIndex;
0211 myValue = theSolution.GetPoint(theIndex);
0212 }
0213
0214 void Init(const IntCurveSurface_HInter& theSolution, const Standard_Integer theIndex)
0215 {
0216 myMathIndex = theIndex;
0217 myValue = theSolution.Point(theIndex).W();
0218 }
0219
0220 Standard_Real Value() const
0221 {
0222 return myValue;
0223 }
0224
0225 Standard_Integer Index() const
0226 {
0227 return myMathIndex;
0228 }
0229
0230 bool operator>(const SolInfo& theOther) const
0231 {
0232 return myValue > theOther.myValue;
0233 }
0234
0235 bool operator<(const SolInfo& theOther) const
0236 {
0237 return myValue < theOther.myValue;
0238 }
0239
0240 bool operator==(const SolInfo& theOther) const
0241 {
0242 return myValue == theOther.myValue;
0243 }
0244
0245 Standard_Real& ChangeValue()
0246 {
0247 return myValue;
0248 }
0249
0250 private:
0251 Standard_Integer myMathIndex;
0252 Standard_Real myValue;
0253 };
0254
0255 static
0256 void BoundedArc (const TheArc& A,
0257 const Handle(TheTopolTool)& Domain,
0258 const Standard_Real Pdeb,
0259 const Standard_Real Pfin,
0260 TheFunction& Func,
0261 IntStart_SequenceOfPathPoint& pnt,
0262 IntStart_SequenceOfSegment& seg,
0263 const Standard_Real TolBoundary,
0264 const Standard_Real TolTangency,
0265 Standard_Boolean& Arcsol,
0266 const Standard_Boolean RecheckOnRegularity)
0267 {
0268 // Recherche des points solutions et des bouts d arc solution sur un arc donne.
0269 // On utilise la fonction math_FunctionAllRoots. Ne convient donc que pour
0270 // des arcs ayant un point debut et un point de fin (intervalle ferme de
0271 // parametrage).
0272
0273 Standard_Integer i, Nbi = 0, Nbp = 0;
0274
0275 gp_Pnt ptdeb,ptfin;
0276 Standard_Real pardeb = 0., parfin = 0.;
0277 Standard_Integer ideb,ifin,range,ranged,rangef;
0278
0279 // Creer l echantillonage (math_FunctionSample ou classe heritant)
0280 // Appel a math_FunctionAllRoots
0281
0282 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
0283 //@@@ La Tolerance est asociee a l arc ( Incoherence avec le cheminement )
0284 //@@@ ( EpsX ~ 1e-5 et ResolutionU et V ~ 1e-9 )
0285 //@@@ le vertex trouve ici n'est pas retrouve comme point d arret d une
0286 //@@@ ligne de cheminement
0287 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
0288 Standard_Real EpsX = 1.e-10;
0289 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
0290 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
0291 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
0292
0293 // Standard_Integer NbEchant = TheSOBTool::NbSamplesOnArc(A);
0294 Standard_Integer NbEchant = Func.NbSamples();
0295 if(NbEchant<100) NbEchant = 100; //-- lbr le 22 Avril 96
0296 //-- Toujours des pbs
0297
0298 //-- Modif 24 Aout 93 -----------------------------
0299 Standard_Real nTolTangency = TolTangency;
0300 if((Pfin - Pdeb) < (TolTangency*10.0)) {
0301 nTolTangency=(Pfin-Pdeb)*0.1;
0302 }
0303 if(EpsX>(nTolTangency+nTolTangency)) {
0304 EpsX = nTolTangency * 0.1;
0305 }
0306
0307 //--------------------------------------------------
0308 //-- Plante avec un edge avec 2 Samples
0309 //-- dont les extremites son solutions (f=0)
0310 //-- et ou la derivee est nulle
0311 //-- Exemple : un segment diametre d une sphere
0312 //-- if(NbEchant<3) NbEchant = 3; //-- lbr le 19 Avril 95
0313 //--------------------------------------------------
0314 Standard_Real para=0,dist,maxdist;
0315
0316 //-------------------------------------------------------------- REJECTIONS le 15 oct 98
0317 Standard_Boolean Rejection=Standard_True;
0318 Standard_Real maxdr,maxr,minr,ur,dur;
0319 minr=RealLast();
0320 maxr=-minr;
0321 maxdr=-minr;
0322 dur=(Pfin-Pdeb)*0.2;
0323 for(i=1,ur=Pdeb;i<=6;i++) {
0324 Standard_Real F,D;
0325 if(Func.Values(ur,F,D)) {
0326 Standard_Real lminr,lmaxr;
0327 if(D<0.0) D=-D;
0328 D*=dur+dur;
0329 if(D>maxdr) maxdr=D;
0330 lminr=F-D;
0331 lmaxr=F+D;
0332 if(lminr<minr) minr=lminr;
0333 if(lmaxr>maxr) maxr=lmaxr;
0334 if(minr<0.0 && maxr>0.0) {
0335 Rejection=Standard_False;
0336 break;
0337 }
0338 }
0339 ur+=dur;
0340 }
0341 if(Rejection)
0342 {
0343 dur=0.001+maxdr+(maxr-minr)*0.1;
0344 minr-=dur;
0345 maxr+=dur;
0346 if(minr<0.0 && maxr>0.0) {
0347 Rejection=Standard_False;
0348 }
0349 }
0350
0351 Arcsol=Standard_False;
0352
0353 if(Rejection==Standard_False)
0354 {
0355 const IntSurf_Quadric& aQuadric = Func.Quadric();
0356 GeomAbs_SurfaceType TypeQuad = aQuadric.TypeQuadric();
0357 GeomAbs_CurveType TypeConS = GeomAbs_OtherCurve;
0358
0359 IntCurveSurface_HInter IntCS;
0360 Standard_Boolean IsIntCSdone = Standard_False;
0361 TColStd_SequenceOfReal Params;
0362
0363 std::unique_ptr<math_FunctionAllRoots> pSol;
0364
0365 math_FunctionSample Echant(Pdeb,Pfin,NbEchant);
0366
0367 Standard_Boolean aelargir=Standard_True;
0368 //modified by NIZNHY-PKV Thu Apr 12 09:25:19 2001 f
0369 //
0370 //maxdist = 100.0*TolBoundary;
0371 maxdist = TolBoundary+TolTangency;
0372 //
0373 //modified by NIZNHY-PKV Thu Apr 12 09:25:23 2001 t
0374 for(i=1; i<=NbEchant && aelargir;i++) {
0375 Standard_Real u = Echant.GetParameter(i);
0376 if(Func.Value(u,dist)) {
0377 if(dist>maxdist || -dist>maxdist) {
0378 aelargir=Standard_False;
0379 }
0380 }
0381 }
0382 if(!(aelargir && maxdist<0.01)) {
0383 maxdist = TolBoundary;
0384 }
0385
0386 if (TypeQuad != GeomAbs_OtherSurface) //intersection of boundary curve and quadric surface
0387 {
0388 //Exact solution
0389 Handle(Adaptor3d_Surface) aSurf = Func.Surface();
0390 Adaptor3d_CurveOnSurface ConS(A, aSurf);
0391 TypeConS = ConS.GetType();
0392 #ifdef OCCT_DEBUG
0393 Handle(Geom_Curve) CurveConS;
0394 switch(TypeConS)
0395 {
0396 case GeomAbs_Line:
0397 {
0398 CurveConS = new Geom_Line(ConS.Line());
0399 break;
0400 }
0401 case GeomAbs_Circle:
0402 {
0403 CurveConS = new Geom_Circle(ConS.Circle());
0404 break;
0405 }
0406 case GeomAbs_Ellipse:
0407 {
0408 CurveConS = new Geom_Ellipse(ConS.Ellipse());
0409 break;
0410 }
0411 case GeomAbs_Hyperbola:
0412 {
0413 CurveConS = new Geom_Hyperbola(ConS.Hyperbola());
0414 break;
0415 }
0416 case GeomAbs_Parabola:
0417 {
0418 CurveConS = new Geom_Parabola(ConS.Parabola());
0419 break;
0420 }
0421 case GeomAbs_BezierCurve:
0422 {
0423 CurveConS = ConS.Bezier();
0424 break;
0425 }
0426 case GeomAbs_BSplineCurve:
0427 {
0428 CurveConS = ConS.BSpline();
0429 break;
0430 }
0431 default:
0432 {
0433 Standard_Real MaxDeviation, AverageDeviation;
0434 GeomLib::BuildCurve3d(1.e-5, ConS, ConS.FirstParameter(), ConS.LastParameter(),
0435 CurveConS, MaxDeviation, AverageDeviation);
0436 break;
0437 }
0438 }
0439 #endif
0440 Handle(Adaptor3d_CurveOnSurface) HConS = new Adaptor3d_CurveOnSurface(ConS);
0441 Handle(Geom_Surface) QuadSurf;
0442 switch (TypeQuad)
0443 {
0444 case GeomAbs_Plane:
0445 {
0446 QuadSurf = new Geom_Plane(aQuadric.Plane());
0447 break;
0448 }
0449 case GeomAbs_Cylinder:
0450 {
0451 QuadSurf = new Geom_CylindricalSurface(aQuadric.Cylinder());
0452 break;
0453 }
0454 case GeomAbs_Cone:
0455 {
0456 QuadSurf = new Geom_ConicalSurface(aQuadric.Cone());
0457 break;
0458 }
0459 case GeomAbs_Sphere:
0460 {
0461 QuadSurf = new Geom_SphericalSurface(aQuadric.Sphere());
0462 break;
0463 }
0464 case GeomAbs_Torus:
0465 {
0466 QuadSurf = new Geom_ToroidalSurface(aQuadric.Torus());
0467 break;
0468 }
0469 default:
0470 break;
0471 }
0472 Handle(GeomAdaptor_Surface) GAHsurf = new GeomAdaptor_Surface(QuadSurf);
0473
0474 if ((TypeConS == GeomAbs_Line ||
0475 TypeConS == GeomAbs_Circle ||
0476 TypeConS == GeomAbs_Ellipse ||
0477 TypeConS == GeomAbs_Parabola ||
0478 TypeConS == GeomAbs_Hyperbola) &&
0479 TypeQuad != GeomAbs_Torus &&
0480 !IsDegenerated(HConS) &&
0481 !IsDegenerated(aQuadric))
0482 {
0483 //exact intersection for only canonic curves and real quadric surfaces
0484 IntCS.Perform(HConS, GAHsurf);
0485 }
0486
0487 IsIntCSdone = IntCS.IsDone();
0488 if (IsIntCSdone)
0489 {
0490 Nbp = IntCS.NbPoints();
0491 Nbi = IntCS.NbSegments();
0492 }
0493 //If we have not got intersection, it may be touch with some tolerance,
0494 //need to be checked
0495 if (Nbp == 0 && Nbi == 0)
0496 IsIntCSdone = Standard_False;
0497
0498 } //if (TypeQuad != GeomAbs_OtherSurface) - intersection of boundary curve and quadric surface
0499
0500 if (!IsIntCSdone)
0501 {
0502 pSol.reset(new math_FunctionAllRoots(Func,Echant,EpsX,maxdist,maxdist)); //-- TolBoundary,nTolTangency);
0503
0504 if (!pSol->IsDone()) {throw Standard_Failure();}
0505
0506 Nbp=pSol->NbPoints();
0507 }
0508 //
0509 //jgv: build solution on the whole boundary
0510 if (RecheckOnRegularity && Nbp > 0 && IsRegularity(A, Domain))
0511 {
0512 //Standard_Real theTol = Domain->MaxTolerance(A);
0513 //theTol += theTol;
0514 Standard_Real theTol = 5.e-4;
0515 math_FunctionAllRoots SolAgain(Func,Echant,EpsX,theTol,theTol); //-- TolBoundary,nTolTangency);
0516
0517 if (!SolAgain.IsDone()) {throw Standard_Failure();}
0518
0519 Standard_Integer Nbi_again = SolAgain.NbIntervals();
0520
0521 if (Nbi_again > 0)
0522 {
0523 Standard_Integer NbSamples = 10;
0524 Standard_Real delta = (Pfin - Pdeb)/NbSamples;
0525 Standard_Real GlobalTol = theTol*10;
0526 Standard_Boolean SolOnBoundary = Standard_True;
0527 for (i = 0; i <= NbSamples; i++)
0528 {
0529 Standard_Real aParam = Pdeb + i*delta;
0530 Standard_Real aValue;
0531 Func.Value(aParam, aValue);
0532 if (Abs(aValue) > GlobalTol)
0533 {
0534 SolOnBoundary = Standard_False;
0535 break;
0536 }
0537 }
0538
0539 if (SolOnBoundary)
0540 {
0541 for (i = 1; i <= Nbi_again; i++)
0542 {
0543 IntStart_TheSegment newseg;
0544 newseg.SetValue(A);
0545 // Recuperer point debut et fin, et leur parametre.
0546 SolAgain.GetInterval(i,pardeb,parfin);
0547
0548 if (Abs(pardeb - Pdeb) <= Precision::PConfusion())
0549 pardeb = Pdeb;
0550 if (Abs(parfin - Pfin) <= Precision::PConfusion())
0551 parfin = Pfin;
0552
0553 SolAgain.GetIntervalState(i,ideb,ifin);
0554
0555 //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : i= "<<i<<" ParDeb:"<<pardeb<<" ParFin:"<<parfin<<endl;
0556
0557 ptdeb=Func.Valpoint(ideb);
0558 ptfin=Func.Valpoint(ifin);
0559
0560 PointProcess(ptdeb,pardeb,A,Domain,pnt,theTol,ranged);
0561 newseg.SetLimitPoint(pnt.Value(ranged),Standard_True);
0562 PointProcess(ptfin,parfin,A,Domain,pnt,theTol,rangef);
0563 newseg.SetLimitPoint(pnt.Value(rangef),Standard_False);
0564 seg.Append(newseg);
0565 }
0566 Arcsol=Standard_True;
0567 return;
0568 }
0569 }
0570 } //if (RecheckOnRegularity && Nbp > 0 && IsRegularity(A, Domain))
0571 ////////////////////////////////////////////
0572
0573 //-- detection du cas ou la fonction est quasi tangente et que les
0574 //-- zeros sont quasi confondus.
0575 //-- Dans ce cas on prend le point "milieu"
0576 //-- On suppose que les solutions sont triees.
0577
0578 if(Nbp) {
0579 NCollection_Array1<SolInfo> aSI(1, Nbp);
0580
0581 for(i=1;i<=Nbp;i++)
0582 {
0583 if (IsIntCSdone)
0584 aSI(i).Init(IntCS, i);
0585 else
0586 aSI(i).Init(*pSol, i);
0587 }
0588
0589 std::sort(aSI.begin(), aSI.end());
0590
0591 //modified by NIZNHY-PKV Wed Mar 21 18:34:18 2001 f
0592 //////////////////////////////////////////////////////////
0593 // The treatment of the situation when line(arc) that is
0594 // tangent to cylinder(domain).
0595 // We should have only one solution i.e Nbp=1. Ok?
0596 // But we have 2,3,.. solutions. That is wrong ersult.
0597 // The TreatLC(...) function is dedicated to solve the pb.
0598 // PKV Fri Mar 23 12:17:29 2001
0599
0600 Standard_Integer ip = TreatLC (A, Domain, aQuadric, TolBoundary, pnt);
0601 if (ip) {
0602 //////////////////////////////////////////////////////////
0603 //modified by NIZNHY-PKV Wed Mar 21 18:34:23 2001 t
0604 //
0605 // Using of old usual way proposed by Laurent
0606 //
0607 for(i=1;i<Nbp;i++) {
0608 Standard_Real parap1 = aSI(i + 1).Value();
0609 para = aSI(i).Value();
0610
0611 Standard_Real param=(para+parap1)*0.5;
0612 Standard_Real yf = 0.0;
0613 Standard_Real ym = 0.0;
0614 Standard_Real yl = 0.0;
0615 if(Func.Value(param,ym) && Abs(ym) < maxdist) {
0616 Standard_Real sm = Sign(1., ym);
0617 Standard_Boolean aTang = Func.Value(para,yf) && Func.Value(parap1,yl);
0618 if (aTang) {
0619 //Line can be tangent surface if all distances less then maxdist
0620 aTang = aTang && Abs(yf) < maxdist && Abs(yl) < maxdist;
0621 }
0622 if (aTang && IsIntCSdone && TypeConS == GeomAbs_Line) {
0623 //Interval is got by exact intersection
0624 //Line can be tangent if all points are on the same side of surface
0625 //it means that signs of all distances are the same
0626 Standard_Real sf = Sign(1., yf), sl = Sign(1., yl);
0627 aTang = aTang && (sm == sf) && (sm == sl);
0628 }
0629 if(aTang) {
0630 // Modified by skv - Tue Aug 31 12:13:51 2004 OCC569 Begin
0631 // Consider this interval as tangent one. Treat it to find
0632 // parameter with the lowest function value.
0633 // Compute the number of nodes.
0634 Standard_Real aTol = TolBoundary*1000.0;
0635 if(aTol > 0.001)
0636 aTol = 0.001;
0637
0638 // fix floating point exception 569, chl-922-e9
0639 parap1 = (Abs(parap1) < 1.e9) ? parap1 : ((parap1 >= 0.) ? 1.e9 : -1.e9);
0640 para = (Abs(para) < 1.e9) ? para : ((para >= 0.) ? 1.e9 : -1.e9);
0641
0642 Standard_Integer aNbNodes = RealToInt(Ceiling((parap1 - para)/aTol));
0643
0644 Standard_Real aVal = RealLast();
0645 Standard_Real aValMax = 0.;
0646 //Standard_Integer aNbNodes = 23;
0647 Standard_Real aDelta = (parap1 - para)/(aNbNodes + 1.);
0648 Standard_Integer ii;
0649 Standard_Real aCurPar;
0650 Standard_Real aCurVal;
0651
0652 for (ii = 0; ii <= aNbNodes + 1; ii++) {
0653 aCurPar = (ii < aNbNodes + 1) ? para + ii*aDelta : parap1;
0654
0655 if (Func.Value(aCurPar, aCurVal)) {
0656 Standard_Real anAbsVal = Abs(aCurVal);
0657 if (anAbsVal < aVal) {
0658 aVal = anAbsVal;
0659 param = aCurPar;
0660 }
0661 if (anAbsVal > aValMax)
0662 {
0663 aValMax = anAbsVal;
0664 }
0665 }
0666 }
0667 // At last, interval got by exact intersection can be considered as tangent if
0668 // minimal distance is inside interval and
0669 // minimal and maximal values are almost the same
0670 if (IsIntCSdone && aNbNodes > 1) {
0671 aTang = Abs(param - para) > EpsX && Abs(parap1 - param) > EpsX &&
0672 0.01*aValMax <= aVal;
0673 }
0674 if (aTang)
0675 {
0676 aSI(i).ChangeValue() = Pdeb - 1;
0677 aSI(i + 1).ChangeValue() = param;
0678 }
0679 }
0680 }
0681 }
0682
0683 for (i=1; i<=Nbp; i++) {
0684 para = aSI(i).Value();
0685 if((para-Pdeb)<EpsX || (Pfin-para)<EpsX)
0686 continue;
0687
0688 if(!Func.Value(para,dist))
0689 continue;
0690
0691 dist = Abs(dist);
0692
0693 Standard_Integer anIndx = -1;
0694 //const Standard_Real aParam = Sol->GetPoint(aSI(i).Index());
0695 const Standard_Real aParam = aSI(i).Value();
0696 if (dist < maxdist)
0697 {
0698 if (!IsIntCSdone &&
0699 (Abs(aParam - Pdeb) <= Precision::PConfusion() || Abs(aParam - Pfin) <= Precision::PConfusion()))
0700 {
0701 anIndx = pSol->GetPointState(aSI(i).Index());
0702 }
0703 }
0704
0705 gp_Pnt aPnt(anIndx < 0 ? Func.LastComputedPoint() : Func.Valpoint(anIndx));
0706
0707 if (dist > 0.1*Precision::Confusion())
0708 {
0709 //Precise found points. It results in following:
0710 // 1. Make the vertex nearer to the intersection line
0711 // (see description to issue #27252 in order to
0712 // understand necessity).
0713 // 2. Merge two near vertices to single point.
0714
0715 //All members in TabSol array has already been sorted in increase order.
0716 //Now, we limit precise boundaries in order to avoid changing this order.
0717 const Standard_Real aFPar = (i == 1) ? Pdeb : (para + aSI(i - 1).Value()) / 2.0;
0718 const Standard_Real aLPar = (i == Nbp) ? Pfin : (para + aSI(i + 1).Value()) / 2.0;
0719
0720 MinFunction aNewFunc(Func);
0721 math_BrentMinimum aMin(Precision::Confusion());
0722
0723 aMin.Perform(aNewFunc, aFPar, para, aLPar);
0724 if(aMin.IsDone())
0725 {
0726 para = aMin.Location();
0727 const gp_Pnt2d aP2d(A->Value(para));
0728 aPnt = Func.Surface()->Value(aP2d.X(), aP2d.Y());
0729 }
0730 }
0731
0732 PointProcess(aPnt, para, A, Domain, pnt, TolBoundary, range);
0733 }
0734 }// end of if(ip)
0735 } // end of if(Nbp)
0736
0737 // Pour chaque intervalle trouve faire
0738 // Traiter les extremites comme des points
0739 // Ajouter intervalle dans la liste des segments
0740
0741 if (!IsIntCSdone)
0742 Nbi = pSol->NbIntervals();
0743
0744 if (!RecheckOnRegularity && Nbp) {
0745 //--cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx :Nbp>0 0 <- Nbi "<<Nbi<<endl;
0746 Nbi=0;
0747 }
0748
0749 //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : Nbi : "<<Nbi<<endl;
0750
0751 for (i=1; i<=Nbi; i++) {
0752 IntStart_TheSegment newseg;
0753 newseg.SetValue(A);
0754 // Recuperer point debut et fin, et leur parametre.
0755 if (IsIntCSdone)
0756 {
0757 IntCurveSurface_IntersectionSegment IntSeg = IntCS.Segment(i);
0758 IntCurveSurface_IntersectionPoint End1 = IntSeg.FirstPoint();
0759 IntCurveSurface_IntersectionPoint End2 = IntSeg.SecondPoint();
0760 pardeb = End1.W();
0761 parfin = End2.W();
0762 ptdeb = End1.Pnt();
0763 ptfin = End2.Pnt();
0764 }
0765 else
0766 {
0767 pSol->GetInterval(i,pardeb,parfin);
0768 pSol->GetIntervalState(i,ideb,ifin);
0769
0770 //-- cout<<" Debug : IntStart_SearchOnBoundaries_1.gxx : i= "<<i<<" ParDeb:"<<pardeb<<" ParFin:"<<parfin<<endl;
0771
0772 ptdeb=Func.Valpoint(ideb);
0773 ptfin=Func.Valpoint(ifin);
0774 }
0775
0776 PointProcess(ptdeb,pardeb,A,Domain,pnt,TolBoundary,ranged);
0777 newseg.SetLimitPoint(pnt.Value(ranged),Standard_True);
0778 PointProcess(ptfin,parfin,A,Domain,pnt,TolBoundary,rangef);
0779 newseg.SetLimitPoint(pnt.Value(rangef),Standard_False);
0780 seg.Append(newseg);
0781 }
0782
0783 if (Nbi==1) {
0784 if((Abs(pardeb - Pdeb) < Precision::PConfusion()) &&
0785 (Abs(parfin - Pfin) < Precision::PConfusion()))
0786 {
0787 Arcsol=Standard_True;
0788 }
0789 }
0790 }
0791 }
0792
0793 //=======================================================================
0794 //function : ComputeBoundsfromInfinite
0795 //purpose :
0796 //=======================================================================
0797 // - PROVISIONAL - TEMPORARY - NOT GOOD - NYI - TO DO
0798 // - Temporary - temporary - not good - nyi - to do
0799 void ComputeBoundsfromInfinite(TheFunction& Func,
0800 Standard_Real& PDeb,
0801 Standard_Real& PFin,
0802 Standard_Integer& NbEchant)
0803 {
0804
0805 // - We are looking for parameters for start and end of the arc (2d curve)
0806 // - Infinity, a way to intersect the quadric with a portion of arc
0807 // - Finished.
0808 //
0809 // - The quadric is a plane, a cylinder, a cone and a sphere.
0810 // - Idea: We take any point on the arc and the fact grow
0811 // - Terminals to the signed distance function values or is likely
0812 // - S cancel.
0813 //
0814 // - WARNING: The following calculations provide a very estimated coarse parameters.
0815 // - This avoids the raises and allows a case of Boxes
0816 // - Inifinies walk. It will take this code
0817 // - With curve surface intersections.
0818
0819 NbEchant = 100;
0820
0821 Standard_Real U0 = 0.0;
0822 Standard_Real dU = 0.001;
0823 Standard_Real Dist0,Dist1;
0824
0825 Func.Value(U0 , Dist0);
0826 Func.Value(U0+dU, Dist1);
0827 Standard_Real dDist = Dist1 - Dist0;
0828 if(dDist) {
0829 U0 -= dU*Dist0 / dDist;
0830 PDeb = PFin = U0;
0831 Standard_Real Umin = U0 - 1e5;
0832 Func.Value(Umin , Dist0);
0833 Func.Value(Umin+dU, Dist1);
0834 dDist = Dist1-Dist0;
0835 if(dDist) {
0836 Umin -= dU*Dist0 / dDist;
0837 }
0838 else {
0839 Umin-=10.0;
0840 }
0841 Standard_Real Umax = U0 + 1e8;
0842 Func.Value(Umax , Dist0);
0843 Func.Value(Umax+dU, Dist1);
0844 dDist = Dist1-Dist0;
0845 if(dDist) {
0846 Umax -= dU*Dist0 / dDist;
0847 }
0848 else {
0849 Umax+=10.0;
0850 }
0851 if(Umin>U0) { Umin=U0-10.0; }
0852 if(Umax<U0) { Umax=U0+10.0; }
0853
0854 PFin = Umax + 10. * (Umax - Umin);
0855 PDeb = Umin - 10. * (Umax - Umin);
0856 }
0857 else {
0858 //-- Possibilite de Arc totalement inclu ds Quad
0859 PDeb = 1e10;
0860 PFin = -1e10;
0861 }
0862 }
0863
0864 //=======================================================================
0865 //function : PointProcess
0866 //purpose :
0867 //=======================================================================
0868 void PointProcess (const gp_Pnt& Pt,
0869 const Standard_Real Para,
0870 const TheArc& A,
0871 const Handle(TheTopolTool)& Domain,
0872 IntStart_SequenceOfPathPoint& pnt,
0873 const Standard_Real Tol,
0874 Standard_Integer& Range)
0875 {
0876
0877 // Check to see if a solution point is coincident with a vertex.
0878 // If confused, you should find this vertex in the list of
0879 // Start. It then returns the position of this point in the list pnt.
0880 // Otherwise, add the point in the list.
0881
0882 Standard_Integer k;
0883 Standard_Boolean found,goon;
0884 Standard_Real dist,toler;
0885
0886 Standard_Integer Nbsol = pnt.Length();
0887 TheVertex vtx;
0888 IntStart_ThePathPoint ptsol;
0889
0890 Domain->Initialize(A);
0891 Domain->InitVertexIterator();
0892 found = Standard_False;
0893 goon = Domain->MoreVertex();
0894 while (goon) {
0895 vtx = Domain->Vertex();
0896 dist= Abs(Para-TheSOBTool::Parameter(vtx,A));
0897 toler = TheSOBTool::Tolerance(vtx,A);
0898 #ifdef OCCT_DEBUG
0899 if(toler>0.1) {
0900 std::cout<<"IntStart_SearchOnBoundaries_1.gxx : ** WARNING ** Tol Vertex="<<toler<<std::endl;
0901 std::cout<<" Ou Edge degenere Ou Kro pointu"<<std::endl;
0902 if(toler>10000) toler=1e-7;
0903 }
0904 #endif
0905
0906 if (dist <= toler) {
0907 // Locate the vertex in the list of solutions
0908 k=1;
0909 found = (k>Nbsol);
0910 while (!found) {
0911 ptsol = pnt.Value(k);
0912 if (!ptsol.IsNew()) {
0913 //jag 940608 if (ptsol.Vertex() == vtx && ptsol.Arc() == A) {
0914 if (Domain->Identical(ptsol.Vertex(),vtx) &&
0915 ptsol.Arc() == A &&
0916 Abs(ptsol.Parameter()-Para) <= toler) {
0917 found=Standard_True;
0918 }
0919 else {
0920 k=k+1;
0921 found=(k>Nbsol);
0922 }
0923 }
0924 else {
0925 k=k+1;
0926 found=(k>Nbsol);
0927 }
0928 }
0929 if (k<=Nbsol) { // We find the vertex
0930 Range = k;
0931 }
0932 else { // Otherwise
0933 ptsol.SetValue(Pt,Tol,vtx,A,Para);
0934 pnt.Append(ptsol);
0935 Range = pnt.Length();
0936 }
0937 found = Standard_True;
0938 goon = Standard_False;
0939 }
0940 else {
0941 Domain->NextVertex();
0942 goon = Domain->MoreVertex();
0943 }
0944 }
0945
0946 if (!found) { // No one is falling on a vertex
0947 //jgv: do not add segment's extremities if they already exist
0948 Standard_Boolean found_internal = Standard_False;
0949 for (k = 1; k <= pnt.Length(); k++)
0950 {
0951 ptsol = pnt.Value(k);
0952 if (ptsol.Arc() != A ||
0953 !ptsol.IsNew()) //vertex
0954 continue;
0955 if (Abs(ptsol.Parameter()-Para) <= Precision::PConfusion())
0956 {
0957 found_internal = Standard_True;
0958 Range = k;
0959 }
0960 }
0961 /////////////////////////////////////////////////////////////
0962
0963 if (!found_internal)
0964 {
0965 Standard_Real TOL=Tol;
0966 TOL*=1000.0;
0967 //if(TOL>0.001) TOL=0.001;
0968 if(TOL>0.005) TOL=0.005; //#24643
0969
0970 ptsol.SetValue(Pt,TOL,A,Para);
0971 pnt.Append(ptsol);
0972 Range = pnt.Length();
0973 }
0974 }
0975 }
0976
0977 //=======================================================================
0978 //function : IsRegularity
0979 //purpose :
0980 //=======================================================================
0981 Standard_Boolean IsRegularity(const TheArc& /*A*/,
0982 const Handle(TheTopolTool)& aDomain)
0983 {
0984 Standard_Address anEAddress=aDomain->Edge();
0985 if (anEAddress==NULL) {
0986 return Standard_False;
0987 }
0988
0989 TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
0990
0991 return (BRep_Tool::HasContinuity(*anE));
0992 }
0993
0994 //=======================================================================
0995 //function : TreatLC
0996 //purpose :
0997 //=======================================================================
0998 Standard_Integer TreatLC (const TheArc& A,
0999 const Handle(TheTopolTool)& aDomain,
1000 const IntSurf_Quadric& aQuadric,
1001 const Standard_Real TolBoundary,
1002 IntStart_SequenceOfPathPoint& pnt)
1003 {
1004 Standard_Integer anExitCode=1, aNbExt;
1005
1006 Standard_Address anEAddress=aDomain->Edge();
1007 if (anEAddress==NULL) {
1008 return anExitCode;
1009 }
1010
1011 TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
1012
1013 if (BRep_Tool::Degenerated(*anE)) {
1014 return anExitCode;
1015 }
1016
1017 GeomAbs_CurveType aTypeE;
1018 BRepAdaptor_Curve aBAC(*anE);
1019 aTypeE=aBAC.GetType();
1020
1021 if (aTypeE!=GeomAbs_Line) {
1022 return anExitCode;
1023 }
1024
1025 GeomAbs_SurfaceType aTypeS;
1026 aTypeS=aQuadric.TypeQuadric();
1027
1028 if (aTypeS!=GeomAbs_Cylinder) {
1029 return anExitCode;
1030 }
1031
1032 Standard_Real f, l, U1f, U1l, U2f, U2l, UEgde, TOL, aDist, aR, aRRel, Tol;
1033 Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, f, l);
1034
1035 gp_Cylinder aCyl=aQuadric.Cylinder();
1036 const gp_Ax1& anAx1=aCyl.Axis();
1037 gp_Lin aLin(anAx1);
1038 Handle(Geom_Line) aCAxis=new Geom_Line (aLin);
1039 aR=aCyl.Radius();
1040
1041 U1f = aCAxis->FirstParameter();
1042 U1l = aCAxis->LastParameter();
1043
1044 U2f = aCEdge->FirstParameter();
1045 U2l = aCEdge->LastParameter();
1046
1047
1048 GeomAdaptor_Curve C1, C2;
1049
1050 C1.Load(aCAxis);
1051 C2.Load(aCEdge);
1052
1053 Tol = Precision::PConfusion();
1054
1055 Extrema_ExtCC anExtCC(C1, C2, U1f, U1l, U2f, U2l, Tol, Tol);
1056
1057 aNbExt=anExtCC.NbExt();
1058 if (aNbExt!=1) {
1059 return anExitCode;
1060 }
1061
1062 gp_Pnt P1,PEdge;
1063 Extrema_POnCurv PC1, PC2;
1064
1065 anExtCC.Points(1, PC1, PC2);
1066
1067 P1 =PC1.Value();
1068 PEdge=PC2.Value();
1069
1070 UEgde=PC2.Parameter();
1071
1072 aDist=PEdge.Distance(P1);
1073 aRRel=fabs(aDist-aR)/aR;
1074 if (aRRel > TolBoundary) {
1075 return anExitCode;
1076 }
1077
1078 if (UEgde < (f+TolBoundary) || UEgde > (l-TolBoundary)) {
1079 return anExitCode;
1080 }
1081 //
1082 // Do not wonder !
1083 // It was done as into PointProcess(...) function
1084 //printf("TreatLC()=> tangent line is found\n");
1085 TOL=1000.*TolBoundary;
1086 if(TOL>0.001) TOL=0.001;
1087
1088 IntStart_ThePathPoint ptsol;
1089 ptsol.SetValue(PEdge, TOL, A, UEgde);
1090 pnt.Append(ptsol);
1091
1092 anExitCode=0;
1093 return anExitCode;
1094
1095 }
1096
1097
1098 //=======================================================================
1099 //function : IntStart_SearchOnBoundaries::IntStart_SearchOnBoundaries
1100 //purpose :
1101 //=======================================================================
1102 IntStart_SearchOnBoundaries::IntStart_SearchOnBoundaries ()
1103 : done(Standard_False),
1104 all(Standard_False)
1105 {
1106 }
1107
1108 //=======================================================================
1109 //function : Perform
1110 //purpose :
1111 //=======================================================================
1112 void IntStart_SearchOnBoundaries::Perform (TheFunction& Func,
1113 const Handle(TheTopolTool)& Domain,
1114 const Standard_Real TolBoundary,
1115 const Standard_Real TolTangency,
1116 const Standard_Boolean RecheckOnRegularity)
1117 {
1118
1119 done = Standard_False;
1120 spnt.Clear();
1121 sseg.Clear();
1122
1123 Standard_Boolean Arcsol;
1124 Standard_Real PDeb,PFin, prm, tol;
1125 Standard_Integer i, nbknown, nbfound,index;
1126 gp_Pnt pt;
1127
1128 Domain->Init();
1129
1130 if (Domain->More()) {
1131 all = Standard_True;
1132 }
1133 else {
1134 all = Standard_False;
1135 }
1136
1137 while (Domain->More()) {
1138 TheArc A = Domain->Value();
1139 if (!TheSOBTool::HasBeenSeen(A)) {
1140 Func.Set(A);
1141 FindVertex(A,Domain,Func,spnt,TolBoundary);
1142 TheSOBTool::Bounds(A,PDeb,PFin);
1143 if(Precision::IsNegativeInfinite(PDeb) ||
1144 Precision::IsPositiveInfinite(PFin)) {
1145 Standard_Integer NbEchant;
1146 ComputeBoundsfromInfinite(Func,PDeb,PFin,NbEchant);
1147 }
1148 BoundedArc(A,Domain,PDeb,PFin,Func,spnt,sseg,TolBoundary,TolTangency,Arcsol,RecheckOnRegularity);
1149 all = (all && Arcsol);
1150 }
1151
1152 else {
1153 // as it seems we'll never be here, because
1154 // TheSOBTool::HasBeenSeen(A) always returns FALSE
1155 nbfound = spnt.Length();
1156
1157 // On recupere les points connus
1158 nbknown = TheSOBTool::NbPoints(A);
1159 for (i=1; i<=nbknown; i++) {
1160 TheSOBTool::Value(A,i,pt,tol,prm);
1161 if (TheSOBTool::IsVertex(A,i)) {
1162 TheVertex vtx;
1163 TheSOBTool::Vertex(A,i,vtx);
1164 spnt.Append(IntStart_ThePathPoint(pt,tol,vtx,A,prm));
1165 }
1166 else {
1167 spnt.Append(IntStart_ThePathPoint(pt,tol,A,prm));
1168 }
1169 }
1170 // On recupere les arcs solutions
1171 nbknown = TheSOBTool::NbSegments(A);
1172 for (i=1; i<=nbknown; i++) {
1173 IntStart_TheSegment newseg;
1174 newseg.SetValue(A);
1175 if (TheSOBTool::HasFirstPoint(A,i,index)) {
1176 newseg.SetLimitPoint(spnt.Value(nbfound+index),Standard_True);
1177 }
1178 if (TheSOBTool::HasLastPoint(A,i,index)) {
1179 newseg.SetLimitPoint(spnt.Value(nbfound+index),Standard_False);
1180 }
1181 sseg.Append(newseg);
1182 }
1183 all = (all& TheSOBTool::IsAllSolution(A));
1184 }
1185 Domain->Next();
1186 }
1187 done = Standard_True;
1188 }