1 // Created on: 1995-07-18
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Extrema_GenExtCS.hxx>
19 #include <Adaptor3d_Curve.hxx>
20 #include <Adaptor3d_HCurve.hxx>
21 #include <Adaptor3d_Surface.hxx>
22 #include <Adaptor3d_HSurface.hxx>
23 #include <Geom_OffsetCurve.hxx>
24 #include <Extrema_GlobOptFuncCS.hxx>
25 #include <Extrema_GlobOptFuncConicS.hxx>
26 #include <Extrema_GlobOptFuncCQuadric.hxx>
27 #include <Extrema_POnCurv.hxx>
28 #include <Extrema_POnSurf.hxx>
29 #include <Geom_Hyperbola.hxx>
30 #include <math_FunctionSetRoot.hxx>
31 #include <math_PSO.hxx>
32 #include <math_PSOParticlesPool.hxx>
33 #include <math_Vector.hxx>
34 #include <Precision.hxx>
35 #include <Standard_OutOfRange.hxx>
36 #include <Standard_TypeMismatch.hxx>
37 #include <StdFail_NotDone.hxx>
38 #include <TColgp_Array1OfPnt.hxx>
39 #include <Geom_TrimmedCurve.hxx>
42 const Standard_Real MaxParamVal = 1.0e+10;
43 const Standard_Real aBorderDivisor = 1.0e+4;
44 const Standard_Real HyperbolaLimit = 23.; //ln(MaxParamVal)
46 static Standard_Boolean IsQuadric(const GeomAbs_SurfaceType theSType)
48 if (theSType == GeomAbs_Plane) return Standard_True;
49 if (theSType == GeomAbs_Cylinder) return Standard_True;
50 if (theSType == GeomAbs_Cone) return Standard_True;
51 if (theSType == GeomAbs_Sphere) return Standard_True;
52 if (theSType == GeomAbs_Torus) return Standard_True;
53 return Standard_False;
55 static Standard_Boolean IsConic(const GeomAbs_CurveType theCType)
57 if (theCType == GeomAbs_Line) return Standard_True;
58 if (theCType == GeomAbs_Circle) return Standard_True;
59 if (theCType == GeomAbs_Ellipse) return Standard_True;
60 if (theCType == GeomAbs_Hyperbola) return Standard_True;
61 if (theCType == GeomAbs_Parabola) return Standard_True;
62 return Standard_False;
64 // restrict maximal parameter on hyperbola to avoid FPE
65 static Standard_Real GetCurvMaxParamVal (const Adaptor3d_Curve& theC)
67 if (theC.GetType() == GeomAbs_Hyperbola)
69 return HyperbolaLimit;
71 if (theC.GetType() == GeomAbs_OffsetCurve)
73 Handle(Geom_Curve) aBC (theC.OffsetCurve()->BasisCurve());
74 Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast (aBC);
77 aBC = aTC->BasisCurve();
79 if (aBC->IsKind (STANDARD_TYPE(Geom_Hyperbola)))
80 return HyperbolaLimit;
85 // restrict maximal parameter on surfaces based on hyperbola to avoid FPE
86 static void GetSurfMaxParamVals (const Adaptor3d_Surface& theS,
87 Standard_Real& theUmax, Standard_Real& theVmax)
89 theUmax = theVmax = MaxParamVal;
91 if (theS.GetType() == GeomAbs_SurfaceOfExtrusion)
93 theUmax = GetCurvMaxParamVal (theS.BasisCurve()->Curve());
95 else if (theS.GetType() == GeomAbs_SurfaceOfRevolution)
97 theVmax = GetCurvMaxParamVal (theS.BasisCurve()->Curve());
99 else if (theS.GetType() == GeomAbs_OffsetSurface)
101 GetSurfMaxParamVals (theS.BasisSurface()->Surface(), theUmax, theVmax);
105 //=======================================================================
106 //function : Extrema_GenExtCS
108 //=======================================================================
109 Extrema_GenExtCS::Extrema_GenExtCS()
110 : myDone(Standard_False),
126 //=======================================================================
127 //function : Extrema_GenExtCS
129 //=======================================================================
130 Extrema_GenExtCS::Extrema_GenExtCS(const Adaptor3d_Curve& C,
131 const Adaptor3d_Surface& S,
132 const Standard_Integer NbT,
133 const Standard_Integer NbU,
134 const Standard_Integer NbV,
135 const Standard_Real Tol1,
136 const Standard_Real Tol2)
138 Initialize(S, NbU, NbV, Tol2);
139 Perform(C, NbT, Tol1);
142 //=======================================================================
143 //function : Extrema_GenExtCS
145 //=======================================================================
147 Extrema_GenExtCS::Extrema_GenExtCS (const Adaptor3d_Curve& C,
148 const Adaptor3d_Surface& S,
149 const Standard_Integer NbT,
150 const Standard_Integer NbU,
151 const Standard_Integer NbV,
152 const Standard_Real tmin,
153 const Standard_Real tsup,
154 const Standard_Real Umin,
155 const Standard_Real Usup,
156 const Standard_Real Vmin,
157 const Standard_Real Vsup,
158 const Standard_Real Tol1,
159 const Standard_Real Tol2)
161 Initialize(S, NbU, NbV, Umin,Usup,Vmin,Vsup,Tol2);
162 Perform(C, NbT, tmin, tsup, Tol1);
165 //=======================================================================
166 //function : Initialize
168 //=======================================================================
169 void Extrema_GenExtCS::Initialize (const Adaptor3d_Surface& S,
170 const Standard_Integer NbU,
171 const Standard_Integer NbV,
172 const Standard_Real Tol2)
174 myumin = S.FirstUParameter();
175 myusup = S.LastUParameter();
176 myvmin = S.FirstVParameter();
177 myvsup = S.LastVParameter();
178 Initialize(S,NbU,NbV,myumin,myusup,myvmin,myvsup,Tol2);
181 //=======================================================================
182 //function : Initialize
184 //=======================================================================
185 void Extrema_GenExtCS::Initialize (const Adaptor3d_Surface& S,
186 const Standard_Integer NbU,
187 const Standard_Integer NbV,
188 const Standard_Real Umin,
189 const Standard_Real Usup,
190 const Standard_Real Vmin,
191 const Standard_Real Vsup,
192 const Standard_Real Tol2)
194 myS = (Adaptor3d_SurfacePtr)&S;
203 Standard_Real umaxpar, vmaxpar;
204 GetSurfMaxParamVals(*myS, umaxpar, vmaxpar);
206 if(Precision::IsInfinite (myusup))
210 if(Precision::IsInfinite (myumin))
214 if(Precision::IsInfinite (myvsup))
218 if(Precision::IsInfinite (myvmin))
223 Standard_Real du = (myusup - myumin) / aBorderDivisor;
224 Standard_Real dv = (myvsup - myvmin) / aBorderDivisor;
225 const Standard_Real aMinU = myumin + du;
226 const Standard_Real aMinV = myvmin + dv;
227 const Standard_Real aMaxU = myusup - du;
228 const Standard_Real aMaxV = myvsup - dv;
230 const Standard_Real aStepSU = (aMaxU - aMinU) / myusample;
231 const Standard_Real aStepSV = (aMaxV - aMinV) / myvsample;
233 mySurfPnts = new TColgp_HArray2OfPnt (0, myusample, 0, myvsample);
235 Standard_Real aSU = aMinU;
236 for (Standard_Integer aSUI = 0; aSUI <= myusample; aSUI++, aSU += aStepSU)
238 Standard_Real aSV = aMinV;
239 for (Standard_Integer aSVI = 0; aSVI <= myvsample; aSVI++, aSV += aStepSV)
241 mySurfPnts->ChangeValue (aSUI, aSVI) = myS->Value (aSU, aSV);
246 //=======================================================================
249 //=======================================================================
250 void Extrema_GenExtCS::Perform(const Adaptor3d_Curve& C,
251 const Standard_Integer NbT,
252 const Standard_Real Tol1)
254 mytmin = C.FirstParameter();
255 mytsup = C.LastParameter();
256 Perform(C, NbT, mytmin, mytsup,Tol1);
259 //=======================================================================
262 //=======================================================================
263 void Extrema_GenExtCS::Perform (const Adaptor3d_Curve& C,
264 const Standard_Integer NbT,
265 const Standard_Real tmin,
266 const Standard_Real tsup,
267 const Standard_Real Tol1)
269 myDone = Standard_False;
270 myF.Initialize(C,*myS);
275 // Modif de lvt pour trimer la surface non pas aux infinis mais a +/- 10000
277 Standard_Real trimusup = myusup, trimumin = myumin,trimvsup = myvsup,trimvmin = myvmin;
278 Standard_Real aCMaxVal = GetCurvMaxParamVal (C);
279 if (Precision::IsInfinite(mytsup)){
282 if (Precision::IsInfinite(mytmin)){
286 Standard_Integer aNbVar = 3;
287 GeomAbs_SurfaceType aSType = myS->GetType();
288 if (IsQuadric(aSType))
294 GeomAbs_CurveType aCType = C.GetType();
301 math_Vector Tol(1, 3), TUV(1, 3), TUVinf(1, 3), TUVsup(1, 3);
308 TUVinf(2) = trimumin;
309 TUVinf(3) = trimvmin;
312 TUVsup(2) = trimusup;
313 TUVsup(3) = trimvsup;
315 // Number of particles used in PSO algorithm (particle swarm optimization).
316 const Standard_Integer aNbParticles = 48;
320 GlobMinGenCS(C, aNbParticles, TUVinf, TUVsup, TUV);
322 else if (aNbVar == 2)
324 GlobMinConicS(C, aNbParticles, TUVinf, TUVsup, TUV);
328 GlobMinCQuadric(C, aNbParticles, TUVinf, TUVsup, TUV);
331 // Find min approximation
332 math_FunctionSetRoot anA(myF, Tol);
333 anA.Perform(myF, TUV, TUVinf, TUVsup);
335 myDone = Standard_True;
337 //=======================================================================
338 //function : GlobMinGenCS
340 //=======================================================================
341 void Extrema_GenExtCS::GlobMinGenCS(const Adaptor3d_Curve& theC,
342 const Standard_Integer theNbParticles,
343 const math_Vector& theTUVinf,
344 const math_Vector& theTUVsup,
347 math_PSOParticlesPool aParticles(theNbParticles, 3);
349 math_Vector aMinTUV(1, 3);
350 aMinTUV = theTUVinf + (theTUVsup - theTUVinf) / aBorderDivisor;
352 math_Vector aMaxTUV(1, 3);
353 aMaxTUV = theTUVsup - (theTUVsup - theTUVinf) / aBorderDivisor;
355 Standard_Real aStepCU = (aMaxTUV(1) - aMinTUV(1)) / mytsample;
356 Standard_Real aStepSU = (aMaxTUV(2) - aMinTUV(2)) / myusample;
357 Standard_Real aStepSV = (aMaxTUV(3) - aMinTUV(3)) / myvsample;
359 // Correct number of curve samples in case of low resolution
360 Standard_Integer aNewCsample = mytsample;
361 Standard_Real aScaleFactor = 5.0;
362 Standard_Real aResolutionCU = aStepCU / theC.Resolution(1.0);
364 Standard_Real aMinResolution = aScaleFactor * Min(aResolutionCU,
365 Min(aStepSU / myS->UResolution(1.0), aStepSV / myS->VResolution(1.0)));
367 if (aMinResolution > Epsilon(1.0))
369 if (aResolutionCU > aMinResolution)
371 const Standard_Integer aMaxNbNodes = 50;
373 aNewCsample = Min(aMaxNbNodes,
374 RealToInt(mytsample * aResolutionCU / aMinResolution));
376 aStepCU = (aMaxTUV(1) - aMinTUV(1)) / aNewCsample;
380 // Pre-compute curve sample points.
381 TColgp_Array1OfPnt aCurvPnts(0, aNewCsample);
383 Standard_Real aCU1 = aMinTUV(1);
384 for (Standard_Integer aCUI = 0; aCUI <= aNewCsample; aCUI++, aCU1 += aStepCU)
385 aCurvPnts.SetValue(aCUI, theC.Value(aCU1));
387 PSO_Particle* aParticle = aParticles.GetWorstParticle();
388 // Select specified number of particles from pre-computed set of samples
389 Standard_Real aSU = aMinTUV(2);
390 for (Standard_Integer aSUI = 0; aSUI <= myusample; aSUI++, aSU += aStepSU)
392 Standard_Real aSV = aMinTUV(3);
393 for (Standard_Integer aSVI = 0; aSVI <= myvsample; aSVI++, aSV += aStepSV)
395 Standard_Real aCU2 = aMinTUV(1);
396 for (Standard_Integer aCUI = 0; aCUI <= aNewCsample; aCUI++, aCU2 += aStepCU)
398 Standard_Real aSqDist = mySurfPnts->Value(aSUI, aSVI).SquareDistance(aCurvPnts.Value(aCUI));
400 if (aSqDist < aParticle->Distance)
402 aParticle->Position[0] = aCU2;
403 aParticle->Position[1] = aSU;
404 aParticle->Position[2] = aSV;
406 aParticle->BestPosition[0] = aCU2;
407 aParticle->BestPosition[1] = aSU;
408 aParticle->BestPosition[2] = aSV;
410 aParticle->Distance = aSqDist;
411 aParticle->BestDistance = aSqDist;
413 aParticle = aParticles.GetWorstParticle();
419 math_Vector aStep(1, 3);
424 // Find min approximation
425 Standard_Real aValue;
426 Extrema_GlobOptFuncCS aFunc(&theC, myS);
427 math_PSO aPSO(&aFunc, theTUVinf, theTUVsup, aStep);
428 aPSO.Perform(aParticles, theNbParticles, aValue, theTUV);
431 //=======================================================================
432 //function : GlobMinConicS
434 //=======================================================================
435 void Extrema_GenExtCS::GlobMinConicS(const Adaptor3d_Curve& theC,
436 const Standard_Integer theNbParticles,
437 const math_Vector& theTUVinf,
438 const math_Vector& theTUVsup,
441 Standard_Integer aNbVar = 2;
442 math_Vector anUVinf(1, aNbVar), anUVsup(1, aNbVar), anUV(1, aNbVar);
444 for (i = 1; i <= aNbVar; ++i)
446 anUVinf(i) = theTUVinf(i + 1);
447 anUVsup(i) = theTUVsup(i + 1);
450 math_PSOParticlesPool aParticles(theNbParticles, aNbVar);
452 math_Vector aMinUV(1, aNbVar);
453 aMinUV = anUVinf + (anUVsup - anUVinf) / aBorderDivisor;
455 math_Vector aMaxUV(1, aNbVar);
456 aMaxUV = anUVsup - (anUVsup - anUVinf) / aBorderDivisor;
458 //Increase numbers of UV samples to improve searching global minimum
459 Standard_Integer anAddsample = Max(mytsample / 2, 3);
460 Standard_Integer anUsample = myusample + anAddsample;
461 Standard_Integer aVsample = myvsample + anAddsample;
463 Standard_Real aStepSU = (aMaxUV(1) - aMinUV(1)) / anUsample;
464 Standard_Real aStepSV = (aMaxUV(2) - aMinUV(2)) / aVsample;
466 Extrema_GlobOptFuncConicS aFunc(myS, anUVinf(1), anUVsup(1), anUVinf(2), anUVsup(2));
467 aFunc.LoadConic(&theC, theTUVinf(1), theTUVsup(1));
470 PSO_Particle* aParticle = aParticles.GetWorstParticle();
471 // Select specified number of particles from pre-computed set of samples
472 Standard_Real aSU = aMinUV(1);
474 for (Standard_Integer aSUI = 0; aSUI <= anUsample; aSUI++, aSU += aStepSU)
477 Standard_Real aSV = aMinUV(2);
478 for (Standard_Integer aSVI = 0; aSVI <= aVsample; aSVI++, aSV += aStepSV)
481 Standard_Real aSqDist;
482 if (!aFunc.Value(anUV, aSqDist))
484 aSqDist = Precision::Infinite();
487 if (aSqDist < aParticle->Distance)
489 aParticle->Position[0] = aSU;
490 aParticle->Position[1] = aSV;
492 aParticle->BestPosition[0] = aSU;
493 aParticle->BestPosition[1] = aSV;
495 aParticle->Distance = aSqDist;
496 aParticle->BestDistance = aSqDist;
498 aParticle = aParticles.GetWorstParticle();
503 math_Vector aStep(1, aNbVar);
507 // Find min approximation
508 Standard_Real aValue;
509 math_PSO aPSO(&aFunc, anUVinf, anUVsup, aStep);
510 aPSO.Perform(aParticles, theNbParticles, aValue, anUV);
512 Standard_Real aCT = aFunc.ConicParameter(anUV);
513 if (theC.IsPeriodic())
515 if (aCT < theTUVinf(1) - Precision::PConfusion() || aCT > theTUVsup(1) + Precision::PConfusion())
517 aCT = ElCLib::InPeriod(aCT, theTUVinf(1), theTUVinf(1) + 2. * M_PI);
525 //=======================================================================
526 //function : GlobMinCQuadric
528 //=======================================================================
529 void Extrema_GenExtCS::GlobMinCQuadric(const Adaptor3d_Curve& theC,
530 const Standard_Integer theNbParticles,
531 const math_Vector& theTUVinf,
532 const math_Vector& theTUVsup,
535 Standard_Integer aNbVar = 1;
536 math_Vector aTinf(1, aNbVar), aTsup(1, aNbVar), aT(1, aNbVar);
537 aTinf(1) = theTUVinf(1);
538 aTsup(1) = theTUVsup(1);
540 math_PSOParticlesPool aParticles(theNbParticles, aNbVar);
542 math_Vector aMinT(1, aNbVar);
543 aMinT = aTinf + (aTsup - aTinf) / aBorderDivisor;
545 math_Vector aMaxT(1, aNbVar);
546 aMaxT = aTsup - (aTsup - aTinf) / aBorderDivisor;
549 //Increase numbers of curve samples to improve searching global minimum
550 //because dimension of optimisation task is redused
551 const Standard_Integer aMaxNbNodes = 50;
552 Standard_Integer aNewCsample = mytsample;
553 Standard_Integer anAddsample = Max(myusample / 2, 3);
554 aNewCsample += anAddsample;
555 aNewCsample = Min(aNewCsample, aMaxNbNodes);
557 // Correct number of curve samples in case of low resolution
558 Standard_Real aStepCT = (aMaxT(1) - aMinT(1)) / aNewCsample;
559 Standard_Real aStepSU = (theTUVsup(2) - theTUVinf(2)) / myusample;
560 Standard_Real aStepSV = (theTUVsup(3) - theTUVinf(3)) / myvsample;
561 Standard_Real aScaleFactor = 5.0;
562 Standard_Real aResolutionCU = aStepCT / theC.Resolution(1.0);
564 Standard_Real aMinResolution = aScaleFactor * Min(aResolutionCU,
565 Min(aStepSU / myS->UResolution(1.0), aStepSV / myS->VResolution(1.0)));
567 if (aMinResolution > Epsilon(1.0))
569 if (aResolutionCU > aMinResolution)
572 aNewCsample = Min(aMaxNbNodes,
573 RealToInt(aNewCsample * aResolutionCU / aMinResolution));
575 aStepCT = (aMaxT(1) - aMinT(1)) / aNewCsample;
580 Extrema_GlobOptFuncCQuadric aFunc(&theC, aTinf(1), aTsup(1));
581 aFunc.LoadQuad(myS, theTUVinf(2), theTUVsup(2), theTUVinf(3), theTUVsup(3));
583 PSO_Particle* aParticle = aParticles.GetWorstParticle();
584 // Select specified number of particles from pre-computed set of samples
585 Standard_Real aCT = aMinT(1);
586 for (Standard_Integer aCUI = 0; aCUI <= aNewCsample; aCUI++, aCT += aStepCT)
589 Standard_Real aSqDist;
590 if (!aFunc.Value(aT, aSqDist))
592 aSqDist = Precision::Infinite();
595 if (aSqDist < aParticle->Distance)
597 aParticle->Position[0] = aCT;
599 aParticle->BestPosition[0] = aCT;
601 aParticle->Distance = aSqDist;
602 aParticle->BestDistance = aSqDist;
604 aParticle = aParticles.GetWorstParticle();
608 math_Vector aStep(1, aNbVar);
611 // Find min approximation
612 Standard_Real aValue;
613 math_PSO aPSO(&aFunc, aTinf, aTsup, aStep);
614 aPSO.Perform(aParticles, theNbParticles, aValue, aT);
616 math_Vector anUV(1, 2);
617 aFunc.QuadricParameters(aT, anUV);
618 if (myS->IsUPeriodic())
620 if (anUV(1) < theTUVinf(2) - Precision::PConfusion() || anUV(1)> theTUVsup(2) + Precision::PConfusion())
622 anUV(1) = ElCLib::InPeriod(anUV(1), theTUVinf(2), theTUVinf(2) + 2. * M_PI);
626 if (myS->IsVPeriodic())
628 if (anUV(2) < theTUVinf(3) - Precision::PConfusion() || anUV(2)> theTUVsup(3) + Precision::PConfusion())
630 anUV(2) = ElCLib::InPeriod(anUV(2), theTUVinf(3), theTUVinf(3) + 2. * M_PI);
640 //=======================================================================
643 //=======================================================================
644 Standard_Boolean Extrema_GenExtCS::IsDone() const
649 //=======================================================================
652 //=======================================================================
653 Standard_Integer Extrema_GenExtCS::NbExt() const
655 if (!IsDone()) { throw StdFail_NotDone(); }
659 //=======================================================================
662 //=======================================================================
663 Standard_Real Extrema_GenExtCS::SquareDistance(const Standard_Integer N) const
665 if (N < 1 || N > NbExt())
667 throw Standard_OutOfRange();
670 return myF.SquareDistance(N);
673 //=======================================================================
674 //function : PointOnCurve
676 //=======================================================================
677 const Extrema_POnCurv& Extrema_GenExtCS::PointOnCurve(const Standard_Integer N) const
679 if (N < 1 || N > NbExt())
681 throw Standard_OutOfRange();
684 return myF.PointOnCurve(N);
687 //=======================================================================
688 //function : PointOnSurface
690 //=======================================================================
691 const Extrema_POnSurf& Extrema_GenExtCS::PointOnSurface(const Standard_Integer N) const
693 if (N < 1 || N > NbExt())
695 throw Standard_OutOfRange();
698 return myF.PointOnSurface(N);
701 //=======================================================================
702 //function : BidonSurface
704 //=======================================================================
705 Adaptor3d_SurfacePtr Extrema_GenExtCS::BidonSurface() const
707 return (Adaptor3d_SurfacePtr)0L;
710 //=======================================================================
711 //function : BidonCurve
713 //=======================================================================
714 Adaptor3d_CurvePtr Extrema_GenExtCS::BidonCurve() const
716 return (Adaptor3d_CurvePtr)0L;