File indexing completed on 2026-09-15 09:15:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
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
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
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
0068 Extrema_GGenExtCC();
0069
0070
0071 Extrema_GGenExtCC(const TheCurve1& theC1, const TheCurve2& theC2);
0072
0073
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
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
0090 void SetTolerance(const double theTol);
0091
0092
0093 void SetSingleSolutionFlag(const bool theFlag);
0094
0095
0096 bool GetSingleSolutionFlag() const;
0097
0098
0099 void Perform();
0100
0101
0102 bool IsDone() const;
0103
0104
0105 bool IsParallel() const;
0106
0107
0108 int NbExt() const;
0109
0110
0111 double SquareDistance(const int theN = 1) const;
0112
0113
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
0130
0131
0132 namespace
0133 {
0134
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 }
0265
0266
0267
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