5c40e5b70b60f8ceb7770ba612bebeb904478ab5
[occt.git] / src / BRepLib / BRepLib_CheckCurveOnSurface.cxx
1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Adaptor2d_HCurve2d.hxx>
17 #include <Adaptor3d_CurveOnSurface.hxx>
18 #include <Adaptor3d_HSurface.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepLib_CheckCurveOnSurface.hxx>
21 #include <Geom2d_BSplineCurve.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom2d_TrimmedCurve.hxx>
24 #include <Geom2dAdaptor.hxx>
25 #include <Geom2dAdaptor_GHCurve.hxx>
26 #include <Geom_BSplineCurve.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_Plane.hxx>
29 #include <Geom_RectangularTrimmedSurface.hxx>
30 #include <Geom_Surface.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <GeomAdaptor_HCurve.hxx>
33 #include <GeomAdaptor_HSurface.hxx>
34 #include <GeomProjLib.hxx>
35 #include <math_Matrix.hxx>
36 #include <math_MultipleVarFunctionWithHessian.hxx>
37 #include <math_NewtonMinimum.hxx>
38 #include <math_PSO.hxx>
39 #include <math_PSOParticlesPool.hxx>
40 #include <NCollection_Array1.hxx>
41 #include <OSD_Parallel.hxx>
42 #include <ProjLib_ProjectedCurve.hxx>
43 #include <Standard_ErrorHandler.hxx>
44 #include <TColStd_Array1OfReal.hxx>
45 #include <TopoDS.hxx>
46 #include <TopoDS_Edge.hxx>
47 #include <TopoDS_Face.hxx>
48
49 class BRepLib_CheckCurveOnSurface_TargetFunc;
50
51 static 
52 Standard_Boolean MinComputing(
53                 BRepLib_CheckCurveOnSurface_TargetFunc& theFunction,
54                 const Standard_Real theEpsilon, //1.0e-3
55                 const Standard_Integer theNbParticles,
56                 Standard_Real& theBestValue,
57                 Standard_Real& theBestParameter);
58
59 static Standard_Integer FillSubIntervals( const Handle(Geom_Curve)& theCurve3d,
60                                           const Handle(Geom2d_Curve)& theCurve2d,
61                                           const Standard_Real theFirst,
62                                           const Standard_Real theLast,
63                                           Standard_Integer &theNbParticles,
64                                           TColStd_Array1OfReal* const theSubIntervals = 0);
65
66 //=======================================================================
67 //class   : BRepLib_CheckCurveOnSurface_TargetFunc
68 //purpose : Target function (to be minimized)
69 //=======================================================================
70 class BRepLib_CheckCurveOnSurface_TargetFunc :
71   public math_MultipleVarFunctionWithHessian
72 {
73  public:
74   BRepLib_CheckCurveOnSurface_TargetFunc( const Adaptor3d_Curve& theC3D,
75                                           const Adaptor3d_Curve& theAdCS,
76                                           const Standard_Real theFirst,
77                                           const Standard_Real theLast):
78   myCurve1(theC3D),
79   myCurve2(theAdCS),
80   myFirst(theFirst),
81   myLast(theLast)
82   {
83   }
84   
85   //returns the number of parameters of the function
86   //(the function is one-dimension).
87   virtual Standard_Integer NbVariables() const {
88     return 1;
89   }
90   
91   //returns value of the function when parameters are equal to theX
92   virtual Standard_Boolean Value(const math_Vector& theX,
93                                  Standard_Real& theFVal)
94   {
95     return Value(theX(1), theFVal);
96   }
97
98   //returns value of the one-dimension-function when parameter
99   //is equal to theX
100   Standard_Boolean Value( const  Standard_Real theX,
101                           Standard_Real& theFVal) const
102   {
103     try
104     {
105       OCC_CATCH_SIGNALS
106       if (!CheckParameter(theX))
107         return Standard_False;
108
109       const gp_Pnt  aP1(myCurve1.Value(theX)),
110                     aP2(myCurve2.Value(theX));
111       
112       theFVal = -1.0*aP1.SquareDistance(aP2);
113     }
114     catch(Standard_Failure) {
115       return Standard_False;
116     }
117     //
118     return Standard_True;
119   }
120
121   //see analogical method for abstract owner class math_MultipleVarFunction
122   virtual Standard_Integer GetStateNumber()
123   {
124     return 0;
125   }
126   
127   //returns the gradient of the function when parameters are
128   //equal to theX
129   virtual Standard_Boolean Gradient(const math_Vector& theX,
130                                     math_Vector& theGrad)
131   {
132     return Derive(theX(1), theGrad(1));
133   }
134
135   //returns 1st derivative of the the one-dimension-function when
136   //parameter is equal to theX
137   Standard_Boolean Derive(const Standard_Real theX, Standard_Real& theDeriv) const
138   {
139     try
140     {
141       OCC_CATCH_SIGNALS
142       if (!CheckParameter(theX))
143       {
144         return Standard_False;
145       }
146       //
147       gp_Pnt aP1, aP2;
148       gp_Vec aDC1, aDC2;
149       //
150       myCurve1.D1(theX, aP1, aDC1);
151       myCurve2.D1(theX, aP2, aDC2);
152
153       const gp_Vec aVec1(aP1, aP2), aVec2(aDC2-aDC1);
154       //
155       theDeriv = -2.0*aVec1.Dot(aVec2);
156     }
157     catch(Standard_Failure)
158     {
159       return Standard_False;
160     }
161
162     return Standard_True;
163   }
164   
165   //returns value and gradient   
166   virtual Standard_Boolean Values(const math_Vector& theX,
167                                   Standard_Real& theVal,
168                                   math_Vector& theGrad) 
169   {
170     if (!Value(theX, theVal))
171     {
172       return Standard_False;
173     }
174     //
175     if (!Gradient(theX, theGrad)) {
176       return Standard_False;
177     }
178     //
179     return Standard_True;
180   }
181
182   //returns value, gradient and hessian
183   virtual Standard_Boolean Values(const math_Vector& theX,
184                                   Standard_Real& theVal,
185                                   math_Vector& theGrad,
186                                   math_Matrix& theHessian)
187   {
188     if (!Value(theX, theVal))
189     {
190       return Standard_False;
191     }
192     //
193     if (!Gradient(theX, theGrad))
194     {
195       return Standard_False;
196     }
197     //
198     theHessian(1,1) = theGrad(1);
199     //
200     return Standard_True;
201   }
202   //
203   Standard_Real FirstParameter() const
204   {
205     return myFirst;
206   }
207
208   //
209   Standard_Real LastParameter() const
210   {
211     return myLast;
212   }
213   
214  private:
215   BRepLib_CheckCurveOnSurface_TargetFunc operator=(BRepLib_CheckCurveOnSurface_TargetFunc&);
216
217   //checks if the function can be computed when its parameter is
218   //equal to theParam
219    Standard_Boolean CheckParameter(const Standard_Real theParam) const
220    {
221      return ((myFirst <= theParam) && (theParam <= myLast));
222    }
223
224    const Adaptor3d_Curve& myCurve1;
225    const Adaptor3d_Curve& myCurve2;
226    const Standard_Real myFirst;
227    const Standard_Real myLast;
228 };
229
230 //=======================================================================
231 //class   : BRepLib_CheckCurveOnSurface_Local
232 //purpose : Created for parallelization possibility only
233 //=======================================================================
234 class BRepLib_CheckCurveOnSurface_Local
235 {
236 public:
237   BRepLib_CheckCurveOnSurface_Local(
238               const Handle(Geom_Curve)& theCurve3D,
239               const Handle(Geom2d_Curve)& theCurve2D,
240               const Handle(Geom_Surface)& theSurface,
241               const TColStd_Array1OfReal& theIntervalsArr,
242               const Standard_Real theEpsilonRange,
243               const Standard_Integer theNbParticles):
244   myCurve3D(theCurve3D),
245   myCurve2D(theCurve2D),
246   mySurface(theSurface),
247   mySubIntervals(theIntervalsArr),
248   myEpsilonRange(theEpsilonRange),
249   myNbParticles(theNbParticles),
250   myArrOfDist(theIntervalsArr.Lower(), theIntervalsArr.Upper()-1),
251   myArrOfParam(theIntervalsArr.Lower(), theIntervalsArr.Upper()-1)
252   {
253   }
254   
255   void operator()(const Standard_Integer& theIndex) const
256   {
257     //For every sub-interval (which is set by mySubIntervals array) this method
258     //computes optimal value of BRepLib_CheckCurveOnSurface_TargetFunc function.
259     //This optimal value will be put in corresponding (depending on theIndex - the
260     //identificator of the current interval in mySubIntervals array) cell of 
261     //myArrOfDist and myArrOfParam arrays.
262     const GeomAdaptor_Curve anAC(myCurve3D);
263     const Handle(Adaptor2d_HCurve2d) anAd2dC = new Geom2dAdaptor_GHCurve(myCurve2D);
264     const Handle(Adaptor3d_HSurface) anAdS = new GeomAdaptor_HSurface(mySurface);
265
266     const Adaptor3d_CurveOnSurface anACS(anAd2dC, anAdS);
267
268     BRepLib_CheckCurveOnSurface_TargetFunc aFunc( anAC, anACS,
269                                                   mySubIntervals.Value(theIndex),
270                                                   mySubIntervals.Value(theIndex+1));
271
272     Standard_Real aMinDist = RealLast(), aPar = 0.0;
273     if(!MinComputing(aFunc, myEpsilonRange, myNbParticles, aMinDist, aPar))
274     {
275       myArrOfDist(theIndex) = RealLast();
276       myArrOfParam(theIndex) = aFunc.FirstParameter();
277       return;
278     }
279
280     myArrOfDist(theIndex) = aMinDist;
281     myArrOfParam(theIndex) = aPar;
282   }
283
284   //Returns optimal value (inverse of square of maximal distance)
285   void OptimalValues(Standard_Real& theMinimalValue, Standard_Real& theParameter) const
286   {
287     //This method looks for the minimal value of myArrOfDist.
288
289     const Standard_Integer aStartInd = myArrOfDist.Lower();
290     theMinimalValue = myArrOfDist(aStartInd);
291     theParameter = myArrOfParam(aStartInd);
292     for(Standard_Integer i = aStartInd + 1; i <= myArrOfDist.Upper(); i++)
293     {
294       if(myArrOfDist(i) < theMinimalValue)
295       {
296         theMinimalValue = myArrOfDist(i);
297         theParameter = myArrOfParam(i);
298       }
299     }
300   }
301
302 private:
303   BRepLib_CheckCurveOnSurface_Local operator=(BRepLib_CheckCurveOnSurface_Local&);
304   const Handle(Geom_Curve)& myCurve3D;
305   const Handle(Geom2d_Curve)& myCurve2D;
306   const Handle(Geom_Surface)& mySurface;
307
308   const TColStd_Array1OfReal& mySubIntervals;
309   const Standard_Real myEpsilonRange;
310   const Standard_Integer myNbParticles;
311   mutable NCollection_Array1<Standard_Real> myArrOfDist;
312   mutable NCollection_Array1<Standard_Real> myArrOfParam;
313 };
314
315 //=======================================================================
316 //function : BRepLib_CheckCurveOnSurface
317 //purpose  : 
318 //=======================================================================
319 BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface()
320 :
321   myFirst(0.),
322   myLast(0.),
323   myErrorStatus(0),
324   myMaxDistance(RealLast()),
325   myMaxParameter(0.)
326 {
327 }
328
329 //=======================================================================
330 //function : BRepLib_CheckCurveOnSurface
331 //purpose  : 
332 //=======================================================================
333 BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface
334   (const TopoDS_Edge& theEdge,
335    const TopoDS_Face& theFace)
336 :
337   myErrorStatus(0),
338   myMaxDistance(RealLast()),
339   myMaxParameter(0.)
340 {
341   Init(theEdge, theFace);
342 }
343
344 //=======================================================================
345 //function : BRepLib_CheckCurveOnSurface
346 //purpose  : 
347 //=======================================================================
348 BRepLib_CheckCurveOnSurface::BRepLib_CheckCurveOnSurface
349   (const Handle(Geom_Curve)& the3DCurve,
350    const Handle(Geom2d_Curve)& the2DCurve,
351    const Handle(Geom_Surface)& theSurface,
352    const Standard_Real theFirst,
353    const Standard_Real theLast)
354 :
355   myErrorStatus(0),
356   myMaxDistance(RealLast()),
357   myMaxParameter(0.)
358 {
359   Init(the3DCurve, the2DCurve, theSurface, theFirst, theLast);
360 }
361
362 //=======================================================================
363 //function : Init
364 //purpose  : 
365 //=======================================================================
366 void BRepLib_CheckCurveOnSurface::Init
367   (const TopoDS_Edge& theEdge,
368    const TopoDS_Face& theFace)
369 {
370   myCurve.Nullify();
371   myPCurve.Nullify();
372   myPCurve2.Nullify();
373   mySurface.Nullify();
374   myErrorStatus = 0;
375   myMaxDistance = RealLast();
376   myMaxParameter = 0.0;
377   myFirst = 0.0;
378   myLast = 0.0;
379
380   if (theEdge.IsNull() || theFace.IsNull()) {
381     return;
382   }
383   //
384   if (BRep_Tool::Degenerated(theEdge) ||
385       !BRep_Tool::IsGeometric(theEdge)) {
386     return;
387   }
388   //
389   TopLoc_Location aLocE, aLocF, aLocC2D;
390   //
391   // 3D curve initialization
392   const Handle(Geom_Curve)& aC = BRep_Tool::Curve(theEdge, aLocE, myFirst, myLast);
393   myCurve = Handle(Geom_Curve)::DownCast(aC->Transformed(aLocE.Transformation()));
394
395   // Surface initialization
396   const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLocF);
397   mySurface = Handle(Geom_Surface)::DownCast(aS->Transformed(aLocF.Transformation()));
398   //
399   // 2D curves initialization 
400   myPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, myFirst, myLast);
401
402   if(BRep_Tool::IsClosed(theEdge, theFace))
403     myPCurve2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge.Reversed()),
404                                           theFace, myFirst, myLast);
405 }
406
407 //=======================================================================
408 //function : Init
409 //purpose  : 
410 //=======================================================================
411 void BRepLib_CheckCurveOnSurface::Init
412   (const Handle(Geom_Curve)& the3DCurve,
413    const Handle(Geom2d_Curve)& the2DCurve,
414    const Handle(Geom_Surface)& theSurface,
415    const Standard_Real theFirst,
416    const Standard_Real theLast)
417 {
418   myCurve = the3DCurve;
419   myPCurve = the2DCurve;
420   myPCurve2.Nullify();
421   mySurface = theSurface;
422   myFirst = theFirst;
423   myLast  = theLast;
424   myErrorStatus = 0;
425   myMaxDistance = RealLast();
426   myMaxParameter = 0.0;
427 }
428
429 //=======================================================================
430 //function : Perform
431 //purpose  : if isTheMTDisabled == TRUE parallelization is not used
432 //=======================================================================
433 #ifndef HAVE_TBB
434 //After fixing bug # 26365, this fragment should be deleted
435 //(together the text "#ifdef HAVE_TBB")
436
437 void BRepLib_CheckCurveOnSurface::Perform(const Standard_Boolean)
438 {
439   const Standard_Boolean isTheMTDisabled = Standard_True;
440 #else
441 void BRepLib_CheckCurveOnSurface::Perform(const Standard_Boolean isTheMTDisabled)
442 {
443 #endif
444   try {
445     OCC_CATCH_SIGNALS
446     //
447     // 1. Check data
448     CheckData();
449     if (myErrorStatus) {
450       return;
451     }
452
453     // 2. Compute the max distance
454     Compute(myPCurve, isTheMTDisabled);
455     //
456     if (!myPCurve2.IsNull()) {
457       // compute max distance for myPCurve2
458       // (for the second curve on closed surface)
459       Compute(myPCurve2, isTheMTDisabled);
460     }
461   }
462   catch (Standard_Failure) {
463     myErrorStatus = 3;
464   }
465 }
466
467 //=======================================================================
468 //function : Compute
469 //purpose  : if isTheMTDisabled == TRUE parallelization is not used
470 //=======================================================================
471 void BRepLib_CheckCurveOnSurface::Compute(const Handle(Geom2d_Curve)& thePCurve,
472                                           const Standard_Boolean isTheMTDisabled)
473 {
474   const Standard_Real anEpsilonRange = 1.e-3;
475
476   Standard_Integer aNbParticles = 3;
477
478   //Polynomial function with degree n has not more than n-1 maxima and
479   //minima (degree of 1st derivative is equal to n-1 => 1st derivative has
480   //no greater than n-1 roots). Consequently, this function has
481   //maximum n monotonicity intervals. That is a good idea to try to put
482   //at least one particle in every monotonicity interval. Therefore,
483   //number of particles should be equal to n. 
484
485   const Standard_Integer aNbSubIntervals = 
486                               FillSubIntervals( myCurve, thePCurve,
487                                                 myFirst, myLast, aNbParticles);
488
489   if(!aNbSubIntervals)
490   {
491     myErrorStatus = 3;
492     return;
493   }
494
495   TColStd_Array1OfReal anIntervals(1, aNbSubIntervals+1);
496   FillSubIntervals(myCurve, thePCurve, myFirst, myLast, aNbParticles, &anIntervals);
497
498   BRepLib_CheckCurveOnSurface_Local aComp(myCurve, thePCurve,
499                                 mySurface, anIntervals, anEpsilonRange, aNbParticles);
500
501   OSD_Parallel::For(anIntervals.Lower(), anIntervals.Upper(), aComp, isTheMTDisabled);
502
503   aComp.OptimalValues(myMaxDistance, myMaxParameter);
504
505   myMaxDistance = sqrt(Abs(myMaxDistance));
506 }
507
508 //=======================================================================
509 // Function : FillSubIntervals
510 // purpose : Divides [theFirst, theLast] interval on parts
511 //            in order to make searching-algorithm more precisely
512 //            (fills theSubIntervals array).
513 //            Returns number of subintervals.
514 //=======================================================================
515 Standard_Integer FillSubIntervals(const Handle(Geom_Curve)& theCurve3d,
516                                   const Handle(Geom2d_Curve)& theCurve2d,
517                                   const Standard_Real theFirst,
518                                   const Standard_Real theLast,
519                                   Standard_Integer &theNbParticles,
520                                   TColStd_Array1OfReal* const theSubIntervals)
521 {
522   const Standard_Real anArrTempC[2] = {theFirst, theLast};
523   const TColStd_Array1OfReal anArrTemp(anArrTempC[0], 1, 2);
524
525   theNbParticles = 3;
526   Handle(Geom2d_BSplineCurve) aBS2DCurv;
527   Handle(Geom_BSplineCurve) aBS3DCurv;
528
529   //
530   if (theCurve3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
531   {
532     aBS3DCurv = Handle(Geom_BSplineCurve)::
533                       DownCast(Handle(Geom_TrimmedCurve)::
534                       DownCast(theCurve3d)->BasisCurve());
535   }
536   else
537   {
538     aBS3DCurv = Handle(Geom_BSplineCurve)::DownCast(theCurve3d);
539   }
540
541
542   if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
543   {
544     aBS2DCurv = Handle(Geom2d_BSplineCurve)::
545                       DownCast(Handle(Geom2d_TrimmedCurve)::
546                       DownCast(theCurve2d)->BasisCurve());
547   }
548   else
549   {
550     aBS2DCurv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve2d);
551   }
552
553   const TColStd_Array1OfReal &anArrKnots3D = !aBS3DCurv.IsNull() ? 
554                                               aBS3DCurv->Knots() :
555                                               anArrTemp;
556   const TColStd_Array1OfReal &anArrKnots2D = !aBS2DCurv.IsNull() ?
557                                               aBS2DCurv->Knots() :
558                                               anArrTemp;
559
560   Standard_Integer aNbSubIntervals = 1;
561
562   try
563   {
564     OCC_CATCH_SIGNALS
565     const Standard_Integer  anIndMax3D = anArrKnots3D.Upper(),
566                             anIndMax2D = anArrKnots2D.Upper();
567
568     Standard_Integer  anIndex3D = anArrKnots3D.Lower(),
569                       anIndex2D = anArrKnots2D.Lower();
570
571     if(theSubIntervals)
572       theSubIntervals->ChangeValue(aNbSubIntervals) = theFirst;
573
574     while((anIndex3D <= anIndMax3D) && (anIndex2D <= anIndMax2D))
575     {
576       const Standard_Real aVal3D = anArrKnots3D.Value(anIndex3D),
577                           aVal2D = anArrKnots2D.Value(anIndex2D);
578       const Standard_Real aDelta = aVal3D - aVal2D;
579
580       if(aDelta < Precision::PConfusion())
581       {//aVal3D <= aVal2D
582         if((aVal3D > theFirst) && (aVal3D < theLast))
583         {
584           aNbSubIntervals++;
585         
586           if(theSubIntervals)
587             theSubIntervals->ChangeValue(aNbSubIntervals) = aVal3D;
588         }
589
590         anIndex3D++;
591
592         if(-aDelta < Precision::PConfusion())
593         {//aVal3D == aVal2D
594           anIndex2D++;
595         }
596       }
597       else
598       {//aVal2D < aVal3D
599         if((aVal2D > theFirst) && (aVal2D < theLast))
600         {
601           aNbSubIntervals++;
602           
603           if(theSubIntervals)
604             theSubIntervals->ChangeValue(aNbSubIntervals) = aVal2D;
605         }
606
607         anIndex2D++;
608       }
609     }
610
611     if(theSubIntervals)
612       theSubIntervals->ChangeValue(aNbSubIntervals+1) = theLast;
613
614     if(!aBS3DCurv.IsNull())
615     {
616       theNbParticles = Max(theNbParticles, aBS3DCurv->Degree());
617     }
618
619     if(!aBS2DCurv.IsNull())
620     {
621       theNbParticles = Max(theNbParticles, aBS2DCurv->Degree());
622     }
623   }
624   catch(Standard_Failure)
625   {
626 #ifdef OCCT_DEBUG
627     cout << "ERROR! BRepLib_CheckCurveOnSurface.cxx, "
628             "FillSubIntervals(): Incorrect filling!" << endl;
629 #endif
630
631     aNbSubIntervals = 0;
632   }
633
634   return aNbSubIntervals;
635 }
636
637 //=======================================================================
638 //class   : MinComputing
639 //purpose : Performs computing minimal value
640 //=======================================================================
641 Standard_Boolean MinComputing (
642                 BRepLib_CheckCurveOnSurface_TargetFunc& theFunction,
643                 const Standard_Real theEpsilon, //1.0e-3
644                 const Standard_Integer theNbParticles,
645                 Standard_Real& theBestValue,
646                 Standard_Real& theBestParameter)
647 {
648   try
649   {
650     OCC_CATCH_SIGNALS
651
652     //They are used for finding a position of theNbParticles worst places
653     const Standard_Integer aNbControlPoints = 3*theNbParticles;
654     //
655     math_Vector aParInf(1, 1), aParSup(1, 1), anOutputParam(1, 1), aStepPar(1,1);
656     aParInf(1) = theFunction.FirstParameter();
657     aParSup(1) = theFunction.LastParameter();
658     theBestParameter = aParInf(1);
659     theBestValue = RealLast();
660
661     const Standard_Real aDeltaParam = aParSup(1) - aParInf(1);
662     if(aDeltaParam < Precision::PConfusion())
663         return Standard_False;
664
665     aStepPar(1) = theEpsilon*aDeltaParam;
666
667     math_PSOParticlesPool aParticles(theNbParticles, 1);
668
669     const Standard_Real aStep = aDeltaParam/(aNbControlPoints-1);
670     Standard_Integer aCount = 1;
671     for(Standard_Real aPrm = aParInf(1); aCount <= aNbControlPoints; aCount++,
672                       aPrm = (aCount == aNbControlPoints)? aParSup(1) : aPrm+aStep)
673     {
674       Standard_Real aVal = RealLast();
675       theFunction.Value(aPrm, aVal);
676
677       PSO_Particle* aParticle = aParticles.GetWorstParticle();
678
679       if(aVal > aParticle->BestDistance)
680         continue;
681
682       aParticle->Position[0] = aPrm;
683       aParticle->BestPosition[0] = aPrm;
684       aParticle->Distance     = aVal;
685       aParticle->BestDistance = aVal;
686     }
687
688     math_PSO aPSO(&theFunction, aParInf, aParSup, aStepPar);
689     aPSO.Perform(aParticles, theNbParticles, theBestValue, anOutputParam);
690
691     //Here, anOutputParam contains parameter, which is near to optimal.
692     //It needs to be more precise. Precision is made by math_NewtonMinimum.
693     math_NewtonMinimum anA(theFunction);
694     anA.Perform(theFunction, anOutputParam);
695
696     if(!anA.IsDone())
697     {
698 #ifdef OCCT_DEBUG
699       cout << "BRepLib_CheckCurveOnSurface::Compute(): No solution found!" << endl;
700 #endif
701       return Standard_False;
702     }
703
704     anA.Location(anOutputParam);
705     theBestParameter =  anOutputParam(1);
706     theBestValue = anA.Minimum();
707   }
708   catch(Standard_Failure)
709   {
710 #ifdef OCCT_DEBUG
711     cout << "BRepLib_CheckCurveOnSurface.cxx: Exception in MinComputing()!" << endl;
712 #endif
713     return Standard_False;
714   }
715
716   return Standard_True;
717 }