Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 09:15:27

0001 // Created on: 1995-07-18
0002 // Created by: Modelistation
0003 // Copyright (c) 1995-1999 Matra Datavision
0004 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0005 //
0006 // This file is part of Open CASCADE Technology software library.
0007 //
0008 // This library is free software; you can redistribute it and/or modify it under
0009 // the terms of the GNU Lesser General Public License version 2.1 as published
0010 // by the Free Software Foundation, with special exception defined in the file
0011 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0012 // distribution for complete text of the license and disclaimer of any warranty.
0013 //
0014 // Alternatively, this file may be used under the terms of Open CASCADE
0015 // commercial license or contractual agreement.
0016 
0017 #ifndef _Extrema_GGenExtCC_HeaderFile
0018 #define _Extrema_GGenExtCC_HeaderFile
0019 
0020 #include <algorithm>
0021 
0022 #include <Extrema_GlobOptFuncCC.hxx>
0023 #include <GCPnts_AbscissaPoint.hxx>
0024 #include <math_GlobOptMin.hxx>
0025 #include <math_Vector.hxx>
0026 #include <NCollection_CellFilter.hxx>
0027 #include <NCollection_DynamicArray.hxx>
0028 #include <Precision.hxx>
0029 #include <Standard.hxx>
0030 #include <Standard_DefineAlloc.hxx>
0031 #include <Standard_NullObject.hxx>
0032 #include <Standard_OutOfRange.hxx>
0033 #include <StdFail_NotDone.hxx>
0034 #include <NCollection_Array1.hxx>
0035 #include <NCollection_HArray1.hxx>
0036 #include <Standard_Integer.hxx>
0037 #include <NCollection_List.hxx>
0038 #include <NCollection_Sequence.hxx>
0039 
0040 #ifndef M_SQRT2
0041   #define M_SQRT2 1.41421356237309504880168872420969808
0042 #endif
0043 
0044 //! Template class for computing extremal distances between two curves.
0045 //! The function F(u,v)=distance(C1(u),C2(v)) has an extremum when gradient(f)=0.
0046 //! The algorithm uses Evtushenko's global optimization solver.
0047 //!
0048 //! @tparam TheCurve1 Type of the first curve (e.g., Adaptor3d_Curve)
0049 //! @tparam TheCurveTool1 Tool class for the first curve
0050 //! @tparam TheCurve2 Type of the second curve
0051 //! @tparam TheCurveTool2 Tool class for the second curve
0052 //! @tparam ThePOnC Point on curve type (e.g., Extrema_POnCurv)
0053 //! @tparam ThePoint Point type (e.g., gp_Pnt)
0054 //! @tparam TheExtPC Point-to-curve extremum class (e.g., Extrema_ExtPC)
0055 template <typename TheCurve1,
0056           typename TheCurveTool1,
0057           typename TheCurve2,
0058           typename TheCurveTool2,
0059           typename ThePOnC,
0060           typename ThePoint,
0061           typename TheExtPC>
0062 class Extrema_GGenExtCC
0063 {
0064 public:
0065   DEFINE_STANDARD_ALLOC
0066 
0067   //! Default constructor.
0068   Extrema_GGenExtCC();
0069 
0070   //! Constructor with two curves.
0071   Extrema_GGenExtCC(const TheCurve1& theC1, const TheCurve2& theC2);
0072 
0073   //! Constructor with two curves and parameter bounds.
0074   Extrema_GGenExtCC(const TheCurve1& theC1,
0075                     const TheCurve2& theC2,
0076                     const double     theUinf,
0077                     const double     theUsup,
0078                     const double     theVinf,
0079                     const double     theVsup);
0080 
0081   //! Sets parameters for computation.
0082   void SetParams(const TheCurve1& theC1,
0083                  const TheCurve2& theC2,
0084                  const double     theUinf,
0085                  const double     theUsup,
0086                  const double     theVinf,
0087                  const double     theVsup);
0088 
0089   //! Sets the tolerance.
0090   void SetTolerance(const double theTol);
0091 
0092   //! Set flag for single extrema computation.
0093   void SetSingleSolutionFlag(const bool theFlag);
0094 
0095   //! Get flag for single extrema computation.
0096   bool GetSingleSolutionFlag() const;
0097 
0098   //! Performs calculations.
0099   void Perform();
0100 
0101   //! Returns True if the distances are found.
0102   bool IsDone() const;
0103 
0104   //! Returns state of myParallel flag.
0105   bool IsParallel() const;
0106 
0107   //! Returns the number of extremum distances.
0108   int NbExt() const;
0109 
0110   //! Returns the value of the Nth square extremum distance.
0111   double SquareDistance(const int theN = 1) const;
0112 
0113   //! Returns the points of the Nth extremum distance.
0114   void Points(const int theN, ThePOnC& theP1, ThePOnC& theP2) const;
0115 
0116 private:
0117   bool                         myIsFindSingleSolution;
0118   bool                         myParallel;
0119   double                       myCurveMinTol;
0120   math_Vector                  myLowBorder;
0121   math_Vector                  myUppBorder;
0122   NCollection_Sequence<double> myPoints1;
0123   NCollection_Sequence<double> myPoints2;
0124   void*                        myC[2];
0125   bool                         myDone;
0126 };
0127 
0128 //=================================================================================================
0129 // Static helper functions
0130 //=================================================================================================
0131 
0132 namespace
0133 {
0134 // Comparator, used in std::sort.
0135 inline bool Extrema_GGenExtCC_comp(const gp_XY& theA, const gp_XY& theB)
0136 {
0137   if (theA.X() < theB.X())
0138   {
0139     return true;
0140   }
0141   else
0142   {
0143     if (theA.X() == theB.X())
0144     {
0145       if (theA.Y() < theB.Y())
0146         return true;
0147     }
0148   }
0149   return false;
0150 }
0151 
0152 inline void Extrema_GGenExtCC_ChangeIntervals(occ::handle<NCollection_HArray1<double>>& theInts,
0153                                               const int                                 theNbInts)
0154 {
0155   int                                      aNbInts = theInts->Length() - 1;
0156   int                                      aNbAdd  = theNbInts - aNbInts;
0157   occ::handle<NCollection_HArray1<double>> aNewInts =
0158     new NCollection_HArray1<double>(1, theNbInts + 1);
0159   int aNbLast = theInts->Length();
0160   int i;
0161   if (aNbInts == 1)
0162   {
0163     aNewInts->SetValue(1, theInts->First());
0164     aNewInts->SetValue(theNbInts + 1, theInts->Last());
0165     double dt = (theInts->Last() - theInts->First()) / theNbInts;
0166     double t  = theInts->First() + dt;
0167     for (i = 2; i <= theNbInts; ++i, t += dt)
0168     {
0169       aNewInts->SetValue(i, t);
0170     }
0171     theInts = aNewInts;
0172     return;
0173   }
0174   for (i = 1; i <= aNbLast; ++i)
0175   {
0176     aNewInts->SetValue(i, theInts->Value(i));
0177   }
0178   while (aNbAdd > 0)
0179   {
0180     double anLIntMax = -1.;
0181     int    aMaxInd   = -1;
0182     for (i = 1; i < aNbLast; ++i)
0183     {
0184       double anL = aNewInts->Value(i + 1) - aNewInts->Value(i);
0185       if (anL > anLIntMax)
0186       {
0187         anLIntMax = anL;
0188         aMaxInd   = i;
0189       }
0190     }
0191 
0192     double t = (aNewInts->Value(aMaxInd + 1) + aNewInts->Value(aMaxInd)) / 2.;
0193     for (i = aNbLast; i > aMaxInd; --i)
0194     {
0195       aNewInts->SetValue(i + 1, aNewInts->Value(i));
0196     }
0197     aNbLast++;
0198     aNbAdd--;
0199     aNewInts->SetValue(aMaxInd + 1, t);
0200   }
0201   theInts = aNewInts;
0202 }
0203 
0204 class Extrema_GGenExtCC_PointsInspector
0205 {
0206 public:
0207   static constexpr int Dimension = 2;
0208 
0209   typedef gp_XY Point;
0210   typedef gp_XY Target;
0211 
0212   static double Coord(int i, const Point& thePnt) { return thePnt.Coord(i + 1); }
0213 
0214   static Point Shift(const Point& thePnt, double theTol)
0215   {
0216     return Point(thePnt.X() + theTol, thePnt.Y() + theTol);
0217   }
0218 
0219   Extrema_GGenExtCC_PointsInspector(const double theTol)
0220       : myTol(theTol * theTol),
0221         myIsFind(false)
0222   {
0223   }
0224 
0225   void ClearFind() { myIsFind = false; }
0226 
0227   bool isFind() const { return myIsFind; }
0228 
0229   void SetCurrent(const gp_XY& theCurPnt) { myCurrent = theCurPnt; }
0230 
0231   NCollection_CellFilter_Action Inspect(const Target& theObject)
0232   {
0233     gp_XY        aPt     = myCurrent.Subtracted(theObject);
0234     const double aSQDist = aPt.SquareModulus();
0235     if (aSQDist < myTol)
0236     {
0237       myIsFind = true;
0238     }
0239     return CellFilter_Keep;
0240   }
0241 
0242 private:
0243   double myTol;
0244   gp_XY  myCurrent;
0245   bool   myIsFind;
0246 };
0247 
0248 template <typename TheCurve, typename TheExtPCType, typename ThePointType>
0249 double Extrema_GGenExtCC_ProjPOnC(const ThePointType& theP, TheExtPCType& theProjTool)
0250 {
0251   double aDist = ::RealLast();
0252   theProjTool.Perform(theP);
0253   if (theProjTool.IsDone() && theProjTool.NbExt())
0254   {
0255     for (int i = 1; i <= theProjTool.NbExt(); ++i)
0256     {
0257       double aD = theProjTool.SquareDistance(i);
0258       if (aD < aDist)
0259         aDist = aD;
0260     }
0261   }
0262   return aDist;
0263 }
0264 } // namespace
0265 
0266 //=================================================================================================
0267 // Implementation
0268 //=================================================================================================
0269 
0270 //=================================================================================================
0271 
0272 template <typename TheCurve1,
0273           typename TheCurveTool1,
0274           typename TheCurve2,
0275           typename TheCurveTool2,
0276           typename ThePOnC,
0277           typename ThePoint,
0278           typename TheExtPC>
0279 Extrema_GGenExtCC<TheCurve1, TheCurveTool1, TheCurve2, TheCurveTool2, ThePOnC, ThePoint, TheExtPC>::
0280   Extrema_GGenExtCC()
0281     : myIsFindSingleSolution(false),
0282       myParallel(false),
0283       myCurveMinTol(Precision::PConfusion()),
0284       myLowBorder(1, 2),
0285       myUppBorder(1, 2),
0286       myDone(false)
0287 {
0288   myC[0] = myC[1] = nullptr;
0289 }
0290 
0291 //=================================================================================================
0292 
0293 template <typename TheCurve1,
0294           typename TheCurveTool1,
0295           typename TheCurve2,
0296           typename TheCurveTool2,
0297           typename ThePOnC,
0298           typename ThePoint,
0299           typename TheExtPC>
0300 Extrema_GGenExtCC<TheCurve1, TheCurveTool1, TheCurve2, TheCurveTool2, ThePOnC, ThePoint, TheExtPC>::
0301   Extrema_GGenExtCC(const TheCurve1& theC1, const TheCurve2& theC2)
0302     : myIsFindSingleSolution(false),
0303       myParallel(false),
0304       myCurveMinTol(Precision::PConfusion()),
0305       myLowBorder(1, 2),
0306       myUppBorder(1, 2),
0307       myDone(false)
0308 {
0309   myC[0]         = (void*)&theC1;
0310   myC[1]         = (void*)&theC2;
0311   myLowBorder(1) = theC1.FirstParameter();
0312   myLowBorder(2) = theC2.FirstParameter();
0313   myUppBorder(1) = theC1.LastParameter();
0314   myUppBorder(2) = theC2.LastParameter();
0315 }
0316 
0317 //=================================================================================================
0318 
0319 template <typename TheCurve1,
0320           typename TheCurveTool1,
0321           typename TheCurve2,
0322           typename TheCurveTool2,
0323           typename ThePOnC,
0324           typename ThePoint,
0325           typename TheExtPC>
0326 Extrema_GGenExtCC<TheCurve1, TheCurveTool1, TheCurve2, TheCurveTool2, ThePOnC, ThePoint, TheExtPC>::
0327   Extrema_GGenExtCC(const TheCurve1& theC1,
0328                     const TheCurve2& theC2,
0329                     const double     theUinf,
0330                     const double     theUsup,
0331                     const double     theVinf,
0332                     const double     theVsup)
0333     : myIsFindSingleSolution(false),
0334       myParallel(false),
0335       myCurveMinTol(Precision::PConfusion()),
0336       myLowBorder(1, 2),
0337       myUppBorder(1, 2),
0338       myDone(false)
0339 {
0340   myC[0]         = (void*)&theC1;
0341   myC[1]         = (void*)&theC2;
0342   myLowBorder(1) = theUinf;
0343   myLowBorder(2) = theVinf;
0344   myUppBorder(1) = theUsup;
0345   myUppBorder(2) = theVsup;
0346 }
0347 
0348 //=================================================================================================
0349 
0350 template <typename TheCurve1,
0351           typename TheCurveTool1,
0352           typename TheCurve2,
0353           typename TheCurveTool2,
0354           typename ThePOnC,
0355           typename ThePoint,
0356           typename TheExtPC>
0357 void Extrema_GGenExtCC<TheCurve1,
0358                        TheCurveTool1,
0359                        TheCurve2,
0360                        TheCurveTool2,
0361                        ThePOnC,
0362                        ThePoint,
0363                        TheExtPC>::SetParams(const TheCurve1& theC1,
0364                                             const TheCurve2& theC2,
0365                                             const double     theUinf,
0366                                             const double     theUsup,
0367                                             const double     theVinf,
0368                                             const double     theVsup)
0369 {
0370   myC[0]         = (void*)&theC1;
0371   myC[1]         = (void*)&theC2;
0372   myLowBorder(1) = theUinf;
0373   myLowBorder(2) = theVinf;
0374   myUppBorder(1) = theUsup;
0375   myUppBorder(2) = theVsup;
0376 }
0377 
0378 //=================================================================================================
0379 
0380 template <typename TheCurve1,
0381           typename TheCurveTool1,
0382           typename TheCurve2,
0383           typename TheCurveTool2,
0384           typename ThePOnC,
0385           typename ThePoint,
0386           typename TheExtPC>
0387 void Extrema_GGenExtCC<TheCurve1,
0388                        TheCurveTool1,
0389                        TheCurve2,
0390                        TheCurveTool2,
0391                        ThePOnC,
0392                        ThePoint,
0393                        TheExtPC>::SetTolerance(const double theTol)
0394 {
0395   myCurveMinTol = theTol;
0396 }
0397 
0398 //=================================================================================================
0399 
0400 template <typename TheCurve1,
0401           typename TheCurveTool1,
0402           typename TheCurve2,
0403           typename TheCurveTool2,
0404           typename ThePOnC,
0405           typename ThePoint,
0406           typename TheExtPC>
0407 void Extrema_GGenExtCC<TheCurve1,
0408                        TheCurveTool1,
0409                        TheCurve2,
0410                        TheCurveTool2,
0411                        ThePOnC,
0412                        ThePoint,
0413                        TheExtPC>::SetSingleSolutionFlag(const bool theFlag)
0414 {
0415   myIsFindSingleSolution = theFlag;
0416 }
0417 
0418 //=================================================================================================
0419 
0420 template <typename TheCurve1,
0421           typename TheCurveTool1,
0422           typename TheCurve2,
0423           typename TheCurveTool2,
0424           typename ThePOnC,
0425           typename ThePoint,
0426           typename TheExtPC>
0427 bool Extrema_GGenExtCC<TheCurve1,
0428                        TheCurveTool1,
0429                        TheCurve2,
0430                        TheCurveTool2,
0431                        ThePOnC,
0432                        ThePoint,
0433                        TheExtPC>::GetSingleSolutionFlag() const
0434 {
0435   return myIsFindSingleSolution;
0436 }
0437 
0438 //=================================================================================================
0439 
0440 template <typename TheCurve1,
0441           typename TheCurveTool1,
0442           typename TheCurve2,
0443           typename TheCurveTool2,
0444           typename ThePOnC,
0445           typename ThePoint,
0446           typename TheExtPC>
0447 void Extrema_GGenExtCC<TheCurve1,
0448                        TheCurveTool1,
0449                        TheCurve2,
0450                        TheCurveTool2,
0451                        ThePOnC,
0452                        ThePoint,
0453                        TheExtPC>::Perform()
0454 {
0455   myDone     = false;
0456   myParallel = false;
0457 
0458   TheCurve1& C1 = *(TheCurve1*)myC[0];
0459   TheCurve2& C2 = *(TheCurve2*)myC[1];
0460 
0461   int           aNbInter[2];
0462   GeomAbs_Shape aContinuity = GeomAbs_C2;
0463   aNbInter[0]               = C1.NbIntervals(aContinuity);
0464   aNbInter[1]               = C2.NbIntervals(aContinuity);
0465 
0466   if (aNbInter[0] * aNbInter[1] > 100)
0467   {
0468     aContinuity = GeomAbs_C1;
0469     aNbInter[0] = C1.NbIntervals(aContinuity);
0470     aNbInter[1] = C2.NbIntervals(aContinuity);
0471   }
0472 
0473   double       anL[2];
0474   int          indmax = -1, indmin = -1;
0475   const double mult = 20.;
0476   if (!(Precision::IsInfinite(C1.FirstParameter()) || Precision::IsInfinite(C1.LastParameter())
0477         || Precision::IsInfinite(C2.FirstParameter()) || Precision::IsInfinite(C2.LastParameter())))
0478   {
0479     anL[0] = GCPnts_AbscissaPoint::Length(C1);
0480     anL[1] = GCPnts_AbscissaPoint::Length(C2);
0481     if (anL[0] / aNbInter[0] > mult * anL[1] / aNbInter[1])
0482     {
0483       indmax = 0;
0484       indmin = 1;
0485     }
0486     else if (anL[1] / aNbInter[1] > mult * anL[0] / aNbInter[0])
0487     {
0488       indmax = 1;
0489       indmin = 0;
0490     }
0491   }
0492   int aNbIntOpt = 0;
0493   if (indmax >= 0)
0494   {
0495     aNbIntOpt = RealToInt(anL[indmax] * aNbInter[indmin] / anL[indmin] / (mult / 4.)) + 1;
0496     if (aNbIntOpt > 100 || aNbIntOpt < aNbInter[indmax])
0497     {
0498       indmax = -1;
0499     }
0500     else
0501     {
0502       if (aNbIntOpt * aNbInter[indmin] > 100)
0503       {
0504         aNbIntOpt = 100 / aNbInter[indmin];
0505         if (aNbIntOpt < aNbInter[indmax])
0506         {
0507           indmax = -1;
0508         }
0509       }
0510     }
0511   }
0512 
0513   occ::handle<NCollection_HArray1<double>> anIntervals1 =
0514     new NCollection_HArray1<double>(1, aNbInter[0] + 1);
0515   occ::handle<NCollection_HArray1<double>> anIntervals2 =
0516     new NCollection_HArray1<double>(1, aNbInter[1] + 1);
0517   C1.Intervals(anIntervals1->ChangeArray1(), aContinuity);
0518   C2.Intervals(anIntervals2->ChangeArray1(), aContinuity);
0519   if (indmax >= 0)
0520   {
0521     if (indmax == 0)
0522     {
0523       Extrema_GGenExtCC_ChangeIntervals(anIntervals1, aNbIntOpt);
0524       aNbInter[0] = anIntervals1->Length() - 1;
0525     }
0526     else
0527     {
0528       Extrema_GGenExtCC_ChangeIntervals(anIntervals2, aNbIntOpt);
0529       aNbInter[1] = anIntervals2->Length() - 1;
0530     }
0531   }
0532   if (C1.IsClosed() && aNbInter[0] == 1)
0533   {
0534     Extrema_GGenExtCC_ChangeIntervals(anIntervals1, 3);
0535     aNbInter[0] = anIntervals1->Length() - 1;
0536   }
0537   if (C2.IsClosed() && aNbInter[1] == 1)
0538   {
0539     Extrema_GGenExtCC_ChangeIntervals(anIntervals2, 3);
0540     aNbInter[1] = anIntervals2->Length() - 1;
0541   }
0542 
0543   const double aMaxLC   = 10000.;
0544   double       aLC      = 100.0;
0545   const double aMaxDer1 = 1.0 / C1.Resolution(1.0);
0546   const double aMaxDer2 = 1.0 / C2.Resolution(1.0);
0547   double       aMaxDer  = std::max(aMaxDer1, aMaxDer2) * M_SQRT2;
0548   if (aLC > aMaxDer)
0549     aLC = aMaxDer;
0550 
0551   bool         isConstLockedFlag = false;
0552   const double aCR               = 0.001;
0553   if (aMaxDer1 / aMaxDer < aCR || aMaxDer2 / aMaxDer < aCR)
0554   {
0555     isConstLockedFlag = true;
0556   }
0557   if (aMaxDer > aMaxLC)
0558   {
0559     aLC               = aMaxLC;
0560     isConstLockedFlag = true;
0561   }
0562   if (C1.GetType() == GeomAbs_Line)
0563   {
0564     aMaxDer = 1.0 / C2.Resolution(1.0);
0565     if (aLC > aMaxDer)
0566     {
0567       isConstLockedFlag = true;
0568       aLC               = aMaxDer;
0569     }
0570   }
0571   if (C2.GetType() == GeomAbs_Line)
0572   {
0573     aMaxDer = 1.0 / C1.Resolution(1.0);
0574     if (aLC > aMaxDer)
0575     {
0576       isConstLockedFlag = true;
0577       aLC               = aMaxDer;
0578     }
0579   }
0580 
0581   Extrema_GlobOptFuncCCC2 aFunc(C1, C2);
0582   if (aLC < aMaxLC || aMaxDer > aMaxLC)
0583   {
0584     math_Vector aT(1, 2), aG(1, 2);
0585     double      aF, aMaxG = 0.;
0586     double      t1, t2, dt1, dt2;
0587     int         n1 = 21, n2 = 21, i1, i2;
0588     dt1 = (C1.LastParameter() - C1.FirstParameter()) / (n1 - 1);
0589     dt2 = (C2.LastParameter() - C2.FirstParameter()) / (n2 - 1);
0590     for (i1 = 1, t1 = C1.FirstParameter(); i1 <= n1; ++i1, t1 += dt1)
0591     {
0592       aT(1) = t1;
0593       for (i2 = 1, t2 = C2.FirstParameter(); i2 <= n2; ++i2, t2 += dt2)
0594       {
0595         aT(2) = t2;
0596         aFunc.Values(aT, aF, aG);
0597         double aMod = aG(1) * aG(1) + aG(2) * aG(2);
0598         aMaxG       = std::max(aMaxG, aMod);
0599       }
0600     }
0601     aMaxG = std::sqrt(aMaxG);
0602     if (aMaxG > aMaxDer)
0603     {
0604       aLC               = std::min(aMaxG, aMaxLC);
0605       isConstLockedFlag = true;
0606     }
0607     if (aMaxG > 100. * aMaxLC)
0608     {
0609       aLC               = 100. * aMaxLC;
0610       isConstLockedFlag = true;
0611     }
0612     else if (aMaxG < 0.1 * aMaxDer)
0613     {
0614       isConstLockedFlag = true;
0615     }
0616   }
0617   math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
0618   aFinder.SetLipConstState(isConstLockedFlag);
0619   aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
0620   double aDiscTol  = 1.0e-2;
0621   double aValueTol = 1.0e-2;
0622   double aSameTol  = myCurveMinTol / (aDiscTol);
0623   aFinder.SetTol(aDiscTol, aSameTol);
0624   aFinder.SetFunctionalMinimalValue(0.0);
0625 
0626   const double aCellSize = std::max(std::max(anIntervals1->Last() - anIntervals1->First(),
0627                                              anIntervals2->Last() - anIntervals2->First())
0628                                       * Precision::PConfusion() / (2.0 * M_SQRT2),
0629                                     Precision::PConfusion());
0630   Extrema_GGenExtCC_PointsInspector                         anInspector(aCellSize);
0631   NCollection_CellFilter<Extrema_GGenExtCC_PointsInspector> aFilter(aCellSize);
0632   NCollection_DynamicArray<gp_XY>                           aPnts;
0633 
0634   int         i, j, k;
0635   math_Vector aFirstBorderInterval(1, 2);
0636   math_Vector aSecondBorderInterval(1, 2);
0637   double      aF     = RealLast();
0638   double      aCurrF = RealLast();
0639   for (i = 1; i <= aNbInter[0]; i++)
0640   {
0641     for (j = 1; j <= aNbInter[1]; j++)
0642     {
0643       aFirstBorderInterval(1)  = anIntervals1->Value(i);
0644       aFirstBorderInterval(2)  = anIntervals2->Value(j);
0645       aSecondBorderInterval(1) = anIntervals1->Value(i + 1);
0646       aSecondBorderInterval(2) = anIntervals2->Value(j + 1);
0647 
0648       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
0649       aFinder.Perform(GetSingleSolutionFlag());
0650 
0651       aCurrF = aFinder.GetF();
0652       if (aCurrF >= aF + aSameTol * aValueTol)
0653       {
0654         continue;
0655       }
0656 
0657       if (aCurrF > aF - aSameTol * aValueTol)
0658       {
0659         if (aCurrF < aF)
0660           aF = aCurrF;
0661       }
0662       else
0663       {
0664         aF = aCurrF;
0665         aFilter.Reset(aCellSize);
0666         aPnts.Clear();
0667       }
0668 
0669       math_Vector sol(1, 2);
0670       for (k = 1; k <= aFinder.NbExtrema(); k++)
0671       {
0672         aFinder.Points(k, sol);
0673         gp_XY aPnt2d(sol(1), sol(2));
0674 
0675         gp_XY aXYmin = anInspector.Shift(aPnt2d, -aCellSize);
0676         gp_XY aXYmax = anInspector.Shift(aPnt2d, aCellSize);
0677 
0678         anInspector.ClearFind();
0679         anInspector.SetCurrent(aPnt2d);
0680         aFilter.Inspect(aXYmin, aXYmax, anInspector);
0681         if (!anInspector.isFind())
0682         {
0683           aFilter.Add(aPnt2d, aPnt2d);
0684           aPnts.Append(gp_XY(sol(1), sol(2)));
0685         }
0686       }
0687     }
0688   }
0689 
0690   const int aNbSol = aPnts.Length();
0691   if (aNbSol == 0)
0692   {
0693     myDone = false;
0694     return;
0695   }
0696 
0697   myDone = true;
0698 
0699   if (aNbSol == 1)
0700   {
0701     const gp_XY& aSol = aPnts.First();
0702     myPoints1.Append(aSol.X());
0703     myPoints2.Append(aSol.Y());
0704     return;
0705   }
0706 
0707   std::sort(aPnts.begin(), aPnts.end(), Extrema_GGenExtCC_comp);
0708 
0709   NCollection_List<int> aSolutions;
0710 
0711   bool bSaveSolution       = true;
0712   bool bDirsCoinside       = true;
0713   bool bDifferentSolutions = false;
0714 
0715   bool        isParallel = true;
0716   double      aVal       = 0.0;
0717   math_Vector aVec(1, 2, 0.0);
0718 
0719   for (int anIdx = 0; anIdx < aNbSol - 1; anIdx++)
0720   {
0721     const gp_XY& aCurrent = aPnts(anIdx);
0722     const gp_XY& aNext    = aPnts(anIdx + 1);
0723 
0724     aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
0725     aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
0726 
0727     aFunc.Value(aVec, aVal);
0728     if (std::abs(aVal - aF) < Precision::Confusion())
0729     {
0730       if (bSaveSolution)
0731       {
0732         aSolutions.Append(anIdx);
0733         bSaveSolution = false;
0734       }
0735     }
0736     else
0737     {
0738       isParallel = false;
0739       aSolutions.Append(anIdx);
0740       bSaveSolution = true;
0741     }
0742 
0743     if (!bDifferentSolutions)
0744     {
0745       if (aNext.X() > aCurrent.X())
0746       {
0747         if (aNext.Y() > aCurrent.Y())
0748         {
0749           bDifferentSolutions = true;
0750           bDirsCoinside       = true;
0751         }
0752         else if (aNext.Y() < aCurrent.Y())
0753         {
0754           bDifferentSolutions = true;
0755           bDirsCoinside       = false;
0756         }
0757       }
0758     }
0759   }
0760   aSolutions.Append(aNbSol - 1);
0761 
0762   if (!bDifferentSolutions)
0763     isParallel = false;
0764 
0765   if (isParallel)
0766   {
0767     double aT1[2] = {myLowBorder(1), myUppBorder(1)};
0768     double aT2[2] = {bDirsCoinside ? myLowBorder(2) : myUppBorder(2),
0769                      bDirsCoinside ? myUppBorder(2) : myLowBorder(2)};
0770 
0771     TheExtPC anExtPC1, anExtPC2;
0772     anExtPC1.Initialize(C1, myLowBorder(1), myUppBorder(1));
0773     anExtPC2.Initialize(C2, myLowBorder(2), myUppBorder(2));
0774 
0775     for (int iT = 0; isParallel && (iT < 2); ++iT)
0776     {
0777       double aDist1 =
0778         Extrema_GGenExtCC_ProjPOnC<TheCurve2, TheExtPC, ThePoint>(C1.Value(aT1[iT]), anExtPC2);
0779       double aDist2 =
0780         Extrema_GGenExtCC_ProjPOnC<TheCurve1, TheExtPC, ThePoint>(C2.Value(aT2[iT]), anExtPC1);
0781       isParallel = (std::abs(std::min(aDist1, aDist2) - aF * aF) < Precision::Confusion());
0782     }
0783   }
0784 
0785   if (isParallel)
0786   {
0787     const gp_XY& aSol = aPnts.First();
0788     myPoints1.Append(aSol.X());
0789     myPoints2.Append(aSol.Y());
0790     myParallel = true;
0791   }
0792   else
0793   {
0794     NCollection_List<int>::Iterator aItSol(aSolutions);
0795     for (; aItSol.More(); aItSol.Next())
0796     {
0797       const gp_XY& aSol = aPnts(aItSol.Value());
0798       myPoints1.Append(aSol.X());
0799       myPoints2.Append(aSol.Y());
0800     }
0801   }
0802 }
0803 
0804 //=================================================================================================
0805 
0806 template <typename TheCurve1,
0807           typename TheCurveTool1,
0808           typename TheCurve2,
0809           typename TheCurveTool2,
0810           typename ThePOnC,
0811           typename ThePoint,
0812           typename TheExtPC>
0813 bool Extrema_GGenExtCC<TheCurve1,
0814                        TheCurveTool1,
0815                        TheCurve2,
0816                        TheCurveTool2,
0817                        ThePOnC,
0818                        ThePoint,
0819                        TheExtPC>::IsDone() const
0820 {
0821   return myDone;
0822 }
0823 
0824 //=================================================================================================
0825 
0826 template <typename TheCurve1,
0827           typename TheCurveTool1,
0828           typename TheCurve2,
0829           typename TheCurveTool2,
0830           typename ThePOnC,
0831           typename ThePoint,
0832           typename TheExtPC>
0833 bool Extrema_GGenExtCC<TheCurve1,
0834                        TheCurveTool1,
0835                        TheCurve2,
0836                        TheCurveTool2,
0837                        ThePOnC,
0838                        ThePoint,
0839                        TheExtPC>::IsParallel() const
0840 {
0841   if (!IsDone())
0842     throw StdFail_NotDone();
0843   return myParallel;
0844 }
0845 
0846 //=================================================================================================
0847 
0848 template <typename TheCurve1,
0849           typename TheCurveTool1,
0850           typename TheCurve2,
0851           typename TheCurveTool2,
0852           typename ThePOnC,
0853           typename ThePoint,
0854           typename TheExtPC>
0855 int Extrema_GGenExtCC<TheCurve1,
0856                       TheCurveTool1,
0857                       TheCurve2,
0858                       TheCurveTool2,
0859                       ThePOnC,
0860                       ThePoint,
0861                       TheExtPC>::NbExt() const
0862 {
0863   if (!IsDone())
0864     throw StdFail_NotDone();
0865   return myPoints1.Length();
0866 }
0867 
0868 //=================================================================================================
0869 
0870 template <typename TheCurve1,
0871           typename TheCurveTool1,
0872           typename TheCurve2,
0873           typename TheCurveTool2,
0874           typename ThePOnC,
0875           typename ThePoint,
0876           typename TheExtPC>
0877 double Extrema_GGenExtCC<TheCurve1,
0878                          TheCurveTool1,
0879                          TheCurve2,
0880                          TheCurveTool2,
0881                          ThePOnC,
0882                          ThePoint,
0883                          TheExtPC>::SquareDistance(const int theN) const
0884 {
0885   if (theN < 1 || theN > NbExt())
0886   {
0887     throw Standard_OutOfRange();
0888   }
0889 
0890   return TheCurveTool1::Value(*((TheCurve1*)myC[0]), myPoints1(theN))
0891     .SquareDistance(TheCurveTool2::Value(*((TheCurve2*)myC[1]), myPoints2(theN)));
0892 }
0893 
0894 //=================================================================================================
0895 
0896 template <typename TheCurve1,
0897           typename TheCurveTool1,
0898           typename TheCurve2,
0899           typename TheCurveTool2,
0900           typename ThePOnC,
0901           typename ThePoint,
0902           typename TheExtPC>
0903 void Extrema_GGenExtCC<TheCurve1,
0904                        TheCurveTool1,
0905                        TheCurve2,
0906                        TheCurveTool2,
0907                        ThePOnC,
0908                        ThePoint,
0909                        TheExtPC>::Points(const int theN, ThePOnC& theP1, ThePOnC& theP2) const
0910 {
0911   if (theN < 1 || theN > NbExt())
0912   {
0913     throw Standard_OutOfRange();
0914   }
0915 
0916   theP1.SetValues(myPoints1(theN), TheCurveTool1::Value(*((TheCurve1*)myC[0]), myPoints1(theN)));
0917   theP2.SetValues(myPoints2(theN), TheCurveTool2::Value(*((TheCurve2*)myC[1]), myPoints2(theN)));
0918 }
0919 
0920 #endif // _Extrema_GGenExtCC_HeaderFile