0029915: Porting to VC 2017 : Regressions in Modeling Algorithms on VC 2017
[occt.git] / src / Extrema / Extrema_GenExtCC.gxx
CommitLineData
b311480e 1// Created on: 1995-07-18
2// Created by: Modelistation
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
20a216fe 17#include <algorithm>
18
4bbaf12b 19#include <Extrema_GlobOptFuncCC.hxx>
20#include <math_GlobOptMin.hxx>
7fd59977 21#include <Standard_NullObject.hxx>
22#include <Standard_OutOfRange.hxx>
4bbaf12b 23#include <StdFail_NotDone.hxx>
24#include <TColStd_Array1OfReal.hxx>
f9ffd4f9 25#include <TColStd_ListOfInteger.hxx>
7fd59977 26#include <Precision.hxx>
20a216fe 27#include <NCollection_Vector.hxx>
28#include <NCollection_CellFilter.hxx>
56c5a597 29#include <GCPnts_AbscissaPoint.hxx>
20a216fe 30
31// Comparator, used in std::sort.
32static Standard_Boolean comp(const gp_XY& theA,
33 const gp_XY& theB)
34{
35 if (theA.X() < theB.X())
36 {
37 return Standard_True;
38 }
39 else
40 {
41 if (theA.X() == theB.X())
42 {
afb27815 43 if (theA.Y() < theB.Y())
20a216fe 44 return Standard_True;
45 }
46 }
47
48 return Standard_False;
49}
50
56c5a597 51static void ChangeIntervals(Handle(TColStd_HArray1OfReal)& theInts, const Standard_Integer theNbInts)
52{
53 Standard_Integer aNbInts = theInts->Length() - 1;
54 Standard_Integer aNbAdd = theNbInts - aNbInts;
55 Handle(TColStd_HArray1OfReal) aNewInts = new TColStd_HArray1OfReal(1, theNbInts + 1);
56 Standard_Integer aNbLast = theInts->Length();
57 Standard_Integer i;
58 if (aNbInts == 1)
59 {
60 aNewInts->SetValue(1, theInts->First());
61 aNewInts->SetValue(theNbInts + 1, theInts->Last());
62 Standard_Real dt = (theInts->Last() - theInts->First()) / theNbInts;
63 Standard_Real t = theInts->First() + dt;
64 for (i = 2; i <= theNbInts; ++i, t += dt)
65 {
66 aNewInts->SetValue(i, t);
67 }
68 theInts = aNewInts;
69 return;
70 }
71 //
72 for (i = 1; i <= aNbLast; ++i)
73 {
74 aNewInts->SetValue(i, theInts->Value(i));
75 }
76 //
77 while (aNbAdd > 0)
78 {
79 Standard_Real anLIntMax = -1.;
80 Standard_Integer aMaxInd = -1;
81 for (i = 1; i < aNbLast; ++i)
82 {
83 Standard_Real anL = aNewInts->Value(i + 1) - aNewInts->Value(i);
84 if (anL > anLIntMax)
85 {
86 anLIntMax = anL;
87 aMaxInd = i;
88 }
89 }
90
91 Standard_Real t = (aNewInts->Value(aMaxInd + 1) + aNewInts->Value(aMaxInd)) / 2.;
92 for (i = aNbLast; i > aMaxInd; --i)
93 {
94 aNewInts->SetValue(i + 1, aNewInts->Value(i));
95 }
96 aNbLast++;
97 aNbAdd--;
98 aNewInts->SetValue(aMaxInd + 1, t);
99 }
100 theInts = aNewInts;
101}
20a216fe 102class Extrema_CCPointsInspector : public NCollection_CellFilter_InspectorXY
103{
104public:
105 typedef gp_XY Target;
106 //! Constructor; remembers the tolerance
107 Extrema_CCPointsInspector (const Standard_Real theTol)
108 {
109 myTol = theTol * theTol;
110 myIsFind = Standard_False;
111 }
112
113 void ClearFind()
114 {
115 myIsFind = Standard_False;
116 }
117
118 Standard_Boolean isFind()
119 {
120 return myIsFind;
121 }
122
123 //! Set current point to search for coincidence
124 void SetCurrent (const gp_XY& theCurPnt)
125 {
126 myCurrent = theCurPnt;
127 }
128
129 //! Implementation of inspection method
130 NCollection_CellFilter_Action Inspect (const Target& theObject)
131 {
132 gp_XY aPt = myCurrent.Subtracted(theObject);
133 const Standard_Real aSQDist = aPt.SquareModulus();
134 if(aSQDist < myTol)
135 {
136 myIsFind = Standard_True;
137 }
138
139 return CellFilter_Keep;
140 }
141
142private:
143 Standard_Real myTol;
144 gp_XY myCurrent;
145 Standard_Boolean myIsFind;
146};
7fd59977 147
f9ffd4f9 148//=======================================================================
149//function : ProjPOnC
150//purpose : Projects the point on the curve and returns the minimal
151// projection distance
152//=======================================================================
153static Standard_Real ProjPOnC(const Pnt& theP,
154 Extrema_GExtPC& theProjTool)
155{
156 Standard_Real aDist = ::RealLast();
157 theProjTool.Perform(theP);
158 if (theProjTool.IsDone() && theProjTool.NbExt())
159 {
160 for (Standard_Integer i = 1; i <= theProjTool.NbExt(); ++i)
161 {
162 Standard_Real aD = theProjTool.SquareDistance(i);
163 if (aD < aDist)
164 aDist = aD;
165 }
166 aDist = sqrt(aDist);
167 }
168 return aDist;
169}
170
5493d334 171//=======================================================================
172//function : Extrema_GenExtCC
173//purpose :
174//=======================================================================
4bbaf12b 175Extrema_GenExtCC::Extrema_GenExtCC()
836d7b64 176: myIsFindSingleSolution(Standard_False),
177 myParallel(Standard_False),
20a216fe 178 myCurveMinTol(Precision::PConfusion()),
6ca1fa70 179 myLowBorder(1,2),
4bbaf12b 180 myUppBorder(1,2),
181 myDone(Standard_False)
7fd59977 182{
6ca1fa70 183 myC[0] = myC[1] = 0;
7fd59977 184}
185
5493d334 186//=======================================================================
187//function : Extrema_GenExtCC
188//purpose :
189//=======================================================================
190Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
191 const Curve2& C2)
836d7b64 192: myIsFindSingleSolution(Standard_False),
193 myParallel(Standard_False),
20a216fe 194 myCurveMinTol(Precision::PConfusion()),
6ca1fa70 195 myLowBorder(1,2),
4bbaf12b 196 myUppBorder(1,2),
197 myDone(Standard_False)
7fd59977 198{
4bbaf12b 199 myC[0] = (Standard_Address)&C1;
200 myC[1] = (Standard_Address)&C2;
201 myLowBorder(1) = C1.FirstParameter();
202 myLowBorder(2) = C2.FirstParameter();
203 myUppBorder(1) = C1.LastParameter();
204 myUppBorder(2) = C2.LastParameter();
7fd59977 205}
206
5493d334 207//=======================================================================
208//function : Extrema_GenExtCC
209//purpose :
210//=======================================================================
211Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
212 const Curve2& C2,
213 const Standard_Real Uinf,
214 const Standard_Real Usup,
215 const Standard_Real Vinf,
216 const Standard_Real Vsup)
836d7b64 217: myIsFindSingleSolution(Standard_False),
218 myParallel(Standard_False),
20a216fe 219 myCurveMinTol(Precision::PConfusion()),
6ca1fa70 220 myLowBorder(1,2),
4bbaf12b 221 myUppBorder(1,2),
222 myDone(Standard_False)
7fd59977 223{
4bbaf12b 224 myC[0] = (Standard_Address)&C1;
225 myC[1] = (Standard_Address)&C2;
226 myLowBorder(1) = Uinf;
227 myLowBorder(2) = Vinf;
228 myUppBorder(1) = Usup;
229 myUppBorder(2) = Vsup;
7fd59977 230}
231
5493d334 232//=======================================================================
233//function : SetParams
234//purpose :
235//=======================================================================
236void Extrema_GenExtCC::SetParams(const Curve1& C1,
237 const Curve2& C2,
238 const Standard_Real Uinf,
239 const Standard_Real Usup,
240 const Standard_Real Vinf,
241 const Standard_Real Vsup)
7fd59977 242{
4bbaf12b 243 myC[0] = (Standard_Address)&C1;
244 myC[1] = (Standard_Address)&C2;
245 myLowBorder(1) = Uinf;
246 myLowBorder(2) = Vinf;
247 myUppBorder(1) = Usup;
248 myUppBorder(2) = Vsup;
7fd59977 249}
250
5493d334 251//=======================================================================
252//function : SetTolerance
253//purpose :
254//=======================================================================
255void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
256{
257 myCurveMinTol = theTol;
258}
259
260//=======================================================================
261//function : Perform
262//purpose :
263//=======================================================================
264void Extrema_GenExtCC::Perform()
7fd59977 265{
266 myDone = Standard_False;
20a216fe 267 myParallel = Standard_False;
7fd59977 268
4bbaf12b 269 Curve1 &C1 = *(Curve1*)myC[0];
270 Curve2 &C2 = *(Curve2*)myC[1];
271
272 Standard_Integer aNbInter[2];
5333268d 273 GeomAbs_Shape aContinuity = GeomAbs_C2;
274 aNbInter[0] = C1.NbIntervals(aContinuity);
275 aNbInter[1] = C2.NbIntervals(aContinuity);
276
277 if (aNbInter[0] * aNbInter[1] > 100)
278 {
279 aContinuity = GeomAbs_C1;
280 aNbInter[0] = C1.NbIntervals(aContinuity);
281 aNbInter[1] = C2.NbIntervals(aContinuity);
282 }
283
56c5a597 284 Standard_Real anL[2];
285 Standard_Integer indmax = -1, indmin = -1;
286 const Standard_Real mult = 20.;
287 if (!(Precision::IsInfinite(C1.FirstParameter()) || Precision::IsInfinite(C1.LastParameter()) ||
288 Precision::IsInfinite(C2.FirstParameter()) || Precision::IsInfinite(C2.LastParameter())))
289 {
290 anL[0] = GCPnts_AbscissaPoint::Length(C1);
291 anL[1] = GCPnts_AbscissaPoint::Length(C2);
292 if (anL[0] / aNbInter[0] > mult * anL[1] / aNbInter[1])
293 {
294 indmax = 0;
295 indmin = 1;
296 }
297 else if (anL[1] / aNbInter[1] > mult * anL[0] / aNbInter[0])
298 {
299 indmax = 1;
300 indmin = 0;
301 }
302 }
303 Standard_Integer aNbIntOpt = 0;
304 if (indmax >= 0)
305 {
306 aNbIntOpt = RealToInt(anL[indmax] * aNbInter[indmin] / anL[indmin] / (mult / 4.)) + 1;
307 if (aNbIntOpt > 100 || aNbIntOpt < aNbInter[indmax])
308 {
309 indmax = -1;
310 }
311 else
312 {
313 if (aNbIntOpt * aNbInter[indmin] > 100)
314 {
315 aNbIntOpt = 100 / aNbInter[indmin];
316 if (aNbIntOpt < aNbInter[indmax])
317 {
318 indmax = -1;
319 }
320 }
321 }
322 }
323
324 Handle(TColStd_HArray1OfReal) anIntervals1 = new TColStd_HArray1OfReal(1, aNbInter[0] + 1);
325 Handle(TColStd_HArray1OfReal) anIntervals2 = new TColStd_HArray1OfReal(1, aNbInter[1] + 1);
326 C1.Intervals(anIntervals1->ChangeArray1(), aContinuity);
327 C2.Intervals(anIntervals2->ChangeArray1(), aContinuity);
328 if (indmax >= 0)
329 {
330 if (indmax == 0)
331 {
332 //Change anIntervals1
333 ChangeIntervals(anIntervals1, aNbIntOpt);
334 aNbInter[0] = anIntervals1->Length() - 1;
335 }
336 else
337 {
338 //Change anIntervals2;
339 ChangeIntervals(anIntervals2, aNbIntOpt);
340 aNbInter[1] = anIntervals2->Length() - 1;
341 }
342 }
4bbaf12b 343
246c7a75 344 // Lipchitz constant computation.
35dced1c 345 const Standard_Real aMaxLC = 10000.;
1907fb9a 346 Standard_Real aLC = 9.0; // Default value.
246c7a75 347 const Standard_Real aMaxDer1 = 1.0 / C1.Resolution(1.0);
348 const Standard_Real aMaxDer2 = 1.0 / C2.Resolution(1.0);
7856b126 349 Standard_Real aMaxDer = Max(aMaxDer1, aMaxDer2) * Sqrt(2.0);
246c7a75 350 if (aLC > aMaxDer)
351 aLC = aMaxDer;
352
353 // Change constant value according to the concrete curve types.
1907fb9a 354 Standard_Boolean isConstLockedFlag = Standard_False;
b4930287 355 //To prevent LipConst to became too small
356 const Standard_Real aCR = 0.001;
357 if (aMaxDer1 / aMaxDer < aCR || aMaxDer2 / aMaxDer < aCR)
358 {
359 isConstLockedFlag = Standard_True;
360 }
35dced1c 361 if (aMaxDer > aMaxLC)
362 {
363 aLC = aMaxLC;
364 isConstLockedFlag = Standard_True;
365 }
1907fb9a 366 if (C1.GetType() == GeomAbs_Line)
367 {
7856b126 368 aMaxDer = 1.0 / C2.Resolution(1.0);
1907fb9a 369 if (aLC > aMaxDer)
370 {
371 isConstLockedFlag = Standard_True;
372 aLC = aMaxDer;
373 }
374 }
375 if (C2.GetType() == GeomAbs_Line)
376 {
7856b126 377 aMaxDer = 1.0 / C1.Resolution(1.0);
1907fb9a 378 if (aLC > aMaxDer)
379 {
380 isConstLockedFlag = Standard_True;
381 aLC = aMaxDer;
382 }
383 }
384
6ca1fa70 385 Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
1907fb9a 386 math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
387 aFinder.SetLipConstState(isConstLockedFlag);
5333268d 388 aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
5493d334 389 Standard_Real aDiscTol = 1.0e-2;
390 Standard_Real aValueTol = 1.0e-2;
391 Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
392 aFinder.SetTol(aDiscTol, aSameTol);
1907fb9a 393 aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
4bbaf12b 394
20a216fe 395 // Size computed to have cell index inside of int32 value.
56c5a597 396 const Standard_Real aCellSize = Max(Max(anIntervals1->Last() - anIntervals1->First(),
397 anIntervals2->Last() - anIntervals2->First())
f9ffd4f9 398 * Precision::PConfusion() / (2.0 * Sqrt(2.0)),
399 Precision::PConfusion());
f84bf635 400 Extrema_CCPointsInspector anInspector(aCellSize);
a7653f4f 401 NCollection_CellFilter<Extrema_CCPointsInspector> aFilter(aCellSize);
20a216fe 402 NCollection_Vector<gp_XY> aPnts;
6ca1fa70 403
4bbaf12b 404 Standard_Integer i,j,k;
405 math_Vector aFirstBorderInterval(1,2);
406 math_Vector aSecondBorderInterval(1,2);
20a216fe 407 Standard_Real aF = RealLast(); // Best functional value.
408 Standard_Real aCurrF = RealLast(); // Current functional value computed on current interval.
4bbaf12b 409 for(i = 1; i <= aNbInter[0]; i++)
410 {
411 for(j = 1; j <= aNbInter[1]; j++)
412 {
56c5a597 413 aFirstBorderInterval(1) = anIntervals1->Value(i);
414 aFirstBorderInterval(2) = anIntervals2->Value(j);
415 aSecondBorderInterval(1) = anIntervals1->Value(i + 1);
416 aSecondBorderInterval(2) = anIntervals2->Value(j + 1);
4bbaf12b 417
418 aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
836d7b64 419 aFinder.Perform(GetSingleSolutionFlag());
4bbaf12b 420
20a216fe 421 // Check that solution found on current interval is not worse than previous.
4bbaf12b 422 aCurrF = aFinder.GetF();
6ca1fa70 423 if (aCurrF >= aF + aSameTol * aValueTol)
4bbaf12b 424 {
6ca1fa70 425 continue;
426 }
427
20a216fe 428 // Clean previously computed solution if current one is better.
6ca1fa70 429 if (aCurrF > aF - aSameTol * aValueTol)
430 {
431 if (aCurrF < aF)
4bbaf12b 432 aF = aCurrF;
6ca1fa70 433 }
434 else
435 {
436 aF = aCurrF;
20a216fe 437 aFilter.Reset(aCellSize);
438 aPnts.Clear();
6ca1fa70 439 }
7fd59977 440
20a216fe 441 // Save found solutions avoiding repetitions.
6ca1fa70 442 math_Vector sol(1,2);
443 for(k = 1; k <= aFinder.NbExtrema(); k++)
4bbaf12b 444 {
6ca1fa70 445 aFinder.Points(k, sol);
20a216fe 446 gp_XY aPnt2d(sol(1), sol(2));
6ca1fa70 447
20a216fe 448 gp_XY aXYmin = anInspector.Shift(aPnt2d, -aCellSize);
449 gp_XY aXYmax = anInspector.Shift(aPnt2d, aCellSize);
450
451 anInspector.ClearFind();
452 anInspector.SetCurrent(aPnt2d);
453 aFilter.Inspect(aXYmin, aXYmax, anInspector);
454 if (!anInspector.isFind())
6ca1fa70 455 {
20a216fe 456 // Point is out of close cells, add new one.
457 aFilter.Add(aPnt2d, aPnt2d);
458 aPnts.Append(gp_XY(sol(1), sol(2)));
6ca1fa70 459 }
4bbaf12b 460 }
7fd59977 461 }
4bbaf12b 462 }
7fd59977 463
f9ffd4f9 464 const Standard_Integer aNbSol = aPnts.Length();
465 if (aNbSol == 0)
20a216fe 466 {
467 // No solutions.
468 myDone = Standard_False;
469 return;
470 }
471
f9ffd4f9 472 myDone = Standard_True;
473
474 if (aNbSol == 1)
475 {
476 // Single solution
477 const gp_XY& aSol = aPnts.First();
478 myPoints1.Append(aSol.X());
479 myPoints2.Append(aSol.Y());
480 return;
481 }
482
483 // More than one solution is found.
20a216fe 484 // Check for infinity solutions case, for this:
485 // Sort points lexicographically and check midpoint between each two neighboring points.
f9ffd4f9 486 // If all midpoints functional value is acceptable then check the projection distances
487 // of the bounding points of the curves onto the opposite curves.
488 // If these distances are also acceptable set myParallel flag to true and return one solution.
20a216fe 489 std::sort(aPnts.begin(), aPnts.end(), comp);
f9ffd4f9 490
491 // Solutions to pass into result.
492 // If the parallel segment is found, save only extreme solutions on that segment.
493 // The first and last solutions will always be the extreme ones, thus save them unconditionally.
494 TColStd_ListOfInteger aSolutions;
495
496 // Manages the addition of the solution into result.
497 // Set it to TRUE to add the first solution.
498 Standard_Boolean bSaveSolution = Standard_True;
499
500 // Define direction of the second curve relatively the first one
501 // (it will be needed for projection).
502 Standard_Boolean bDirsCoinside = Standard_True;
503 // Check also if the found solutions are not concentrated in one point
504 // on any of the curves. And if they are, avoid marking the curves as parallel.
505 Standard_Boolean bDifferentSolutions = Standard_False;
506
507 Standard_Boolean isParallel = Standard_True;
20a216fe 508 Standard_Real aVal = 0.0;
f9ffd4f9 509 math_Vector aVec(1, 2, 0.0);
20a216fe 510
f9ffd4f9 511 // Iterate on all solutions and collect the extreme solutions on all parallel segments.
512 for (Standard_Integer anIdx = 0; anIdx < aNbSol - 1; anIdx++)
20a216fe 513 {
f9ffd4f9 514 const gp_XY& aCurrent = aPnts(anIdx);
515 const gp_XY& aNext = aPnts(anIdx + 1);
20a216fe 516
f9ffd4f9 517 aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
518 aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
20a216fe 519
f9ffd4f9 520 aFunc.Value(aVec, aVal);
521
522 if (Abs(aVal - aF) < Precision::Confusion())
523 {
524 // It seems the parallel segment is found.
525 // Save only extreme solutions on that segment.
526 if (bSaveSolution)
527 {
528 // Add current solution as the beginning of the parallel segment.
529 aSolutions.Append(anIdx);
530 // Do not keep the next solution in current parallel segment.
531 bSaveSolution = Standard_False;
532 }
533 }
534 else
535 {
536 // Mid point does not satisfy the tolerance criteria, curves are not parallel.
537 isParallel = Standard_False;
538 // Add current solution as the last one in previous parallel segment.
539 aSolutions.Append(anIdx);
540 // Save also the next solution as the first one in next parallel segment.
541 bSaveSolution = Standard_True;
542 }
20a216fe 543
f9ffd4f9 544 if (!bDifferentSolutions)
545 {
546 if (aNext.X() > aCurrent.X())
20a216fe 547 {
f9ffd4f9 548 if (aNext.Y() > aCurrent.Y())
549 {
550 bDifferentSolutions = Standard_True;
551 bDirsCoinside = Standard_True;
552 }
553 else if (aNext.Y() < aCurrent.Y())
554 {
555 bDifferentSolutions = Standard_True;
556 bDirsCoinside = Standard_False;
557 }
20a216fe 558 }
559 }
560 }
f9ffd4f9 561 // Save the last solution
562 aSolutions.Append(aNbSol - 1);
563
564 if (!bDifferentSolutions)
565 isParallel = Standard_False;
566
567 if (isParallel)
568 {
569 // For the check on parallel case it is also necessary to check additionally
570 // if the ends of the curves do not diverge. For this, project the bounding
571 // points of the curves on the opposite curves and check the distances.
572
573 Standard_Real aT1[2] = {myLowBorder(1), myUppBorder(1)};
574 Standard_Real aT2[2] = {bDirsCoinside ? myLowBorder(2) : myUppBorder(2),
575 bDirsCoinside ? myUppBorder(2) : myLowBorder(2)};
576
577 Extrema_GExtPC anExtPC1, anExtPC2;
578 anExtPC1.Initialize(C1, myLowBorder(1), myUppBorder(1));
579 anExtPC2.Initialize(C2, myLowBorder(2), myUppBorder(2));
580
581 for (Standard_Integer iT = 0; isParallel && (iT < 2); ++iT)
582 {
583 Standard_Real aDist1 = ProjPOnC(C1.Value(aT1[iT]), anExtPC2);
584 Standard_Real aDist2 = ProjPOnC(C2.Value(aT2[iT]), anExtPC1);
585 isParallel = (Abs(Min(aDist1, aDist2) - aF) < Precision::Confusion());
586 }
587 }
20a216fe 588
589 if (isParallel)
590 {
f9ffd4f9 591 // Keep only one solution
592 const gp_XY& aSol = aPnts.First();
593 myPoints1.Append(aSol.X());
594 myPoints2.Append(aSol.Y());
20a216fe 595 myParallel = Standard_True;
596 }
597 else
598 {
f9ffd4f9 599 // Keep all saved solutions
600 TColStd_ListIteratorOfListOfInteger aItSol(aSolutions);
601 for (; aItSol.More(); aItSol.Next())
20a216fe 602 {
f9ffd4f9 603 const gp_XY& aSol = aPnts(aItSol.Value());
604 myPoints1.Append(aSol.X());
605 myPoints2.Append(aSol.Y());
20a216fe 606 }
607 }
7fd59977 608}
7fd59977 609
5493d334 610//=======================================================================
611//function : IsDone
612//purpose :
613//=======================================================================
614Standard_Boolean Extrema_GenExtCC::IsDone() const
4bbaf12b 615{
616 return myDone;
617}
7fd59977 618
20a216fe 619//=======================================================================
620//function : IsParallel
621//purpose :
622//=======================================================================
623Standard_Boolean Extrema_GenExtCC::IsParallel() const
624{
638ad7f3 625 if (!IsDone()) throw StdFail_NotDone();
626 return myParallel;
20a216fe 627}
628
5493d334 629//=======================================================================
630//function : NbExt
631//purpose :
632//=======================================================================
633Standard_Integer Extrema_GenExtCC::NbExt() const
7fd59977 634{
638ad7f3 635 if (!IsDone()) throw StdFail_NotDone();
6ca1fa70 636 return myPoints1.Length();
7fd59977 637}
7fd59977 638
5493d334 639//=======================================================================
640//function : SquareDistance
641//purpose :
642//=======================================================================
643Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
7fd59977 644{
638ad7f3 645 if (N < 1 || N > NbExt())
646 {
647 throw Standard_OutOfRange();
648 }
4bbaf12b 649
650 return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
7fd59977 651}
7fd59977 652
5493d334 653//=======================================================================
654//function : Points
655//purpose :
656//=======================================================================
657void Extrema_GenExtCC::Points(const Standard_Integer N,
658 POnC& P1,
659 POnC& P2) const
7fd59977 660{
638ad7f3 661 if (IsParallel())
662 {
663 throw StdFail_InfiniteSolutions();
664 }
665
666 if (N < 1 || N > NbExt())
667 {
668 throw Standard_OutOfRange();
669 }
4bbaf12b 670
671 P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
672 P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
20a216fe 673}
836d7b64 674
675//=======================================================================
676//function : SetSingleSolutionFlag
677//purpose :
678//=======================================================================
679void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
680{
681 myIsFindSingleSolution = theFlag;
682}
683
684//=======================================================================
685//function : GetSingleSolutionFlag
686//purpose :
687//=======================================================================
688Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
689{
690 return myIsFindSingleSolution;
691}