1 // Created on: 1994-07-06
2 // Created by: Laurent PAINNOT
3 // Copyright (c) 1994-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.
17 // Modified by MPS (june 96) : correction du trap dans le cas droite/Bezier
18 // Modified by MPS (mai 97) : PRO 7598
19 // tri des solutions pour eviter de rendre plusieurs
20 // fois la meme solution
22 #include <Adaptor3d_Curve.hxx>
23 #include <Bnd_Range.hxx>
25 #include <Extrema_CurveTool.hxx>
26 #include <Extrema_ECC.hxx>
27 #include <Extrema_ExtCC.hxx>
28 #include <Extrema_ExtElC.hxx>
29 #include <Extrema_ExtPElC.hxx>
30 #include <Extrema_POnCurv.hxx>
31 #include <Extrema_SequenceOfPOnCurv.hxx>
32 #include <Geom_Circle.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_Ellipse.hxx>
35 #include <Geom_Hyperbola.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_Parabola.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <GeomAbs_CurveType.hxx>
41 #include <Precision.hxx>
42 #include <Standard_Failure.hxx>
43 #include <Standard_NotImplemented.hxx>
44 #include <Standard_NullObject.hxx>
45 #include <Standard_OutOfRange.hxx>
46 #include <StdFail_NotDone.hxx>
47 #include <TColStd_Array1OfReal.hxx>
48 #include <TColStd_ListIteratorOfListOfTransient.hxx>
49 #include <TColStd_SequenceOfReal.hxx>
51 //=======================================================================
52 //function : Extrema_ExtCC
54 //=======================================================================
55 Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
56 const Standard_Real TolC2)
57 : myIsFindSingleSolution(Standard_False),
58 myDone (Standard_False),
59 myIsParallel(Standard_False)
61 myC[0] = 0; myC[1] = 0;
62 myInf[0] = myInf[1] = -Precision::Infinite();
63 mySup[0] = mySup[1] = Precision::Infinite();
64 myTol[0] = TolC1; myTol[1] = TolC2;
65 mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
68 //=======================================================================
69 //function : Extrema_ExtCC
71 //=======================================================================
73 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
74 const Adaptor3d_Curve& C2,
75 const Standard_Real U1,
76 const Standard_Real U2,
77 const Standard_Real V1,
78 const Standard_Real V2,
79 const Standard_Real TolC1,
80 const Standard_Real TolC2)
81 : myIsFindSingleSolution(Standard_False),
82 myECC(C1, C2, U1, U2, V1, V2),
83 myDone (Standard_False)
85 SetCurve (1, C1, U1, U2);
86 SetCurve (2, C2, V1, V2);
87 SetTolerance (1, TolC1);
88 SetTolerance (2, TolC2);
89 mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
94 //=======================================================================
95 //function : Extrema_ExtCC
97 //=======================================================================
99 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
100 const Adaptor3d_Curve& C2,
101 const Standard_Real TolC1,
102 const Standard_Real TolC2)
103 : myIsFindSingleSolution(Standard_False),
105 myDone (Standard_False)
107 SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
108 SetCurve (2, C2, C2.FirstParameter(), C2.LastParameter());
109 SetTolerance (1, TolC1);
110 SetTolerance (2, TolC2);
111 mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
115 //=======================================================================
116 //function : Initialize
118 //=======================================================================
119 void Extrema_ExtCC::Initialize (const Adaptor3d_Curve& C1,
120 const Adaptor3d_Curve& C2,
121 const Standard_Real TolC1,
122 const Standard_Real TolC2)
124 // myECC will be re-initialized by Perform()
125 myDone = Standard_False;
126 SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
127 SetCurve (2, C2, C2.FirstParameter(), C2.LastParameter());
128 SetTolerance (1, TolC1);
129 SetTolerance (2, TolC2);
130 mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
133 //=======================================================================
134 //function : Initialize
136 //=======================================================================
137 void Extrema_ExtCC::Initialize (const Adaptor3d_Curve& C1,
138 const Adaptor3d_Curve& C2,
139 const Standard_Real U1,
140 const Standard_Real U2,
141 const Standard_Real V1,
142 const Standard_Real V2,
143 const Standard_Real TolC1,
144 const Standard_Real TolC2)
146 // myECC will be re-initialized by Perform()
147 myDone = Standard_False;
148 SetCurve (1, C1, U1, U2);
149 SetCurve (2, C2, V1, V2);
150 SetTolerance (1, TolC1);
151 SetTolerance (2, TolC2);
152 mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
155 //=======================================================================
156 //function : SetCurve
158 //=======================================================================
160 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C)
162 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetCurve()")
163 Standard_Integer anInd = theRank - 1;
167 //=======================================================================
168 //function : SetCurve
170 //=======================================================================
172 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C,
173 const Standard_Real Uinf, const Standard_Real Usup)
175 SetCurve (theRank, C);
176 SetRange (theRank, Uinf, Usup);
179 //=======================================================================
180 //function : SetRange
182 //=======================================================================
184 void Extrema_ExtCC::SetRange (const Standard_Integer theRank,
185 const Standard_Real Uinf, const Standard_Real Usup)
187 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetRange()")
188 Standard_Integer anInd = theRank - 1;
193 //=======================================================================
194 //function : SetTolerance
196 //=======================================================================
198 void Extrema_ExtCC::SetTolerance (const Standard_Integer theRank, const Standard_Real theTol)
200 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetTolerance()")
201 Standard_Integer anInd = theRank - 1;
202 myTol[anInd] = theTol;
206 //=======================================================================
209 //=======================================================================
211 void Extrema_ExtCC::Perform()
213 Standard_NullObject_Raise_if (!myC[0] || !myC[1], "Extrema_ExtCC::Perform()")
214 myECC.SetParams(*myC[0], *myC[1], myInf[0], mySup[0], myInf[1], mySup[1]);
215 myECC.SetTolerance(Min(myTol[0], myTol[1]));
216 myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
217 myDone = Standard_False;
220 myIsParallel = Standard_False;
222 GeomAbs_CurveType type1 = myC[0]->GetType();
223 GeomAbs_CurveType type2 = myC[1]->GetType();
224 Standard_Real U11, U12, U21, U22, Tol = Min(myTol[0], myTol[1]);
231 if (!Precision::IsInfinite(U11)) myP1f = Extrema_CurveTool::Value(*myC[0], U11);
232 if (!Precision::IsInfinite(U12)) myP1l = Extrema_CurveTool::Value(*myC[0], U12);
233 if (!Precision::IsInfinite(U21)) myP2f = Extrema_CurveTool::Value(*myC[1], U21);
234 if (!Precision::IsInfinite(U22)) myP2l = Extrema_CurveTool::Value(*myC[1], U22);
237 if (Precision::IsInfinite(U11) || Precision::IsInfinite(U21)) mydist11 = RealLast();
238 else mydist11 = myP1f.SquareDistance(myP2f);
239 if (Precision::IsInfinite(U11) || Precision::IsInfinite(U22)) mydist12 = RealLast();
240 else mydist12 = myP1f.SquareDistance(myP2l);
241 if (Precision::IsInfinite(U12) || Precision::IsInfinite(U21)) mydist21 = RealLast();
242 else mydist21 = myP1l.SquareDistance(myP2f);
243 if (Precision::IsInfinite(U12) || Precision::IsInfinite(U22)) mydist22 = RealLast();
244 else mydist22 = myP1l.SquareDistance(myP2l);
246 //Depending on the types of curves, the algorithm is chosen:
247 //- _ExtElC, when one of the curves is a line and the other is elementary,
248 // or there are two circles;
249 //- _GenExtCC, in all other cases
250 if ( (type1 == GeomAbs_Line && type2 <= GeomAbs_Parabola) ||
251 (type2 == GeomAbs_Line && type1 <= GeomAbs_Parabola) ) {
252 //analytical case - one curve is always a line
253 Standard_Integer anInd1 = 0, anInd2 = 1;
254 GeomAbs_CurveType aType2 = type2;
255 Standard_Boolean isInverse = (type1 > type2);
258 //algorithm uses inverse order of arguments
265 Extrema_ExtElC Xtrem (myC[anInd1]->Line(), myC[anInd2]->Line(), Tol);
266 PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
269 case GeomAbs_Circle: {
270 Extrema_ExtElC Xtrem (myC[anInd1]->Line(), myC[anInd2]->Circle(), Tol);
271 PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
274 case GeomAbs_Ellipse: {
275 Extrema_ExtElC Xtrem (myC[anInd1]->Line(), myC[anInd2]->Ellipse());
276 PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
279 case GeomAbs_Hyperbola: {
280 Extrema_ExtElC Xtrem (myC[anInd1]->Line(), myC[anInd2]->Hyperbola());
281 PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
284 case GeomAbs_Parabola: {
285 Extrema_ExtElC Xtrem (myC[anInd1]->Line(), myC[anInd2]->Parabola());
286 PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
291 } else if (type1 == GeomAbs_Circle && type2 == GeomAbs_Circle) {
292 //analytical case - two circles
293 Standard_Boolean bIsDone;
294 Extrema_ExtElC CCXtrem (myC[0]->Circle(), myC[1]->Circle());
295 bIsDone = CCXtrem.IsDone();
297 PrepareResults(CCXtrem, Standard_False, U11, U12, U21, U22);
301 PrepareResults(myECC, U11, U12, U21, U22);
305 PrepareResults(myECC, U11, U12, U21, U22);
310 //=======================================================================
313 //=======================================================================
315 Standard_Boolean Extrema_ExtCC::IsDone() const
320 //=======================================================================
321 //function : IsParallel
323 //=======================================================================
325 Standard_Boolean Extrema_ExtCC::IsParallel() const
329 throw StdFail_NotDone();
336 //=======================================================================
339 //=======================================================================
341 Standard_Real Extrema_ExtCC::SquareDistance(const Standard_Integer N) const
343 if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
344 return mySqDist.Value(N);
348 //=======================================================================
351 //=======================================================================
353 Standard_Integer Extrema_ExtCC::NbExt() const
355 if(!myDone) throw StdFail_NotDone();
356 return mySqDist.Length();
360 //=======================================================================
363 //=======================================================================
365 void Extrema_ExtCC::Points(const Standard_Integer N,
367 Extrema_POnCurv& P2) const
369 if (N < 1 || N > NbExt())
371 throw Standard_OutOfRange();
374 P1 = mypoints.Value(2 * N - 1);
375 P2 = mypoints.Value(2 * N);
380 //=======================================================================
381 //function : TrimmedDistances
383 //=======================================================================
385 void Extrema_ExtCC::TrimmedSquareDistances(Standard_Real& dist11,
386 Standard_Real& dist12,
387 Standard_Real& dist21,
388 Standard_Real& dist22,
392 gp_Pnt& P22 ) const {
404 //=======================================================================
405 //function : ParallelResult
407 //=======================================================================
408 void Extrema_ExtCC::PrepareParallelResult(const Standard_Real theUt11,
409 const Standard_Real theUt12,
410 const Standard_Real theUt21,
411 const Standard_Real theUt22,
412 const Standard_Real theSqDist)
417 const GeomAbs_CurveType aType1 = Extrema_CurveTool::GetType (*myC[0]);
418 const GeomAbs_CurveType aType2 = Extrema_CurveTool::GetType (*myC[1]);
419 if (((aType1 != GeomAbs_Line) && (aType1 != GeomAbs_Circle)) ||
420 ((aType2 != GeomAbs_Line) && (aType2 != GeomAbs_Circle)))
422 mySqDist.Append(theSqDist);
423 myDone = Standard_True;
424 myIsParallel = Standard_True;
428 // Parallel case is only for line-line, circle-circle and circle-line!!!
429 // But really for trimmed curves extremas can not exist!
430 if (aType1 != aType2)
432 //The projection of the circle's location to the trimmed line must exist.
433 const Standard_Boolean isReversed = (aType1 != GeomAbs_Circle);
434 const gp_Pnt aPonC = !isReversed ?
435 Extrema_CurveTool::Value (*myC[0], theUt11) :
436 Extrema_CurveTool::Value (*myC[1], theUt21);
438 const gp_Lin aL = myC[!isReversed ? 1 : 0]->Line();
439 const Extrema_ExtPElC ExtPLin(aPonC, aL, Precision::Confusion(),
440 !isReversed ? theUt21 : theUt11,
441 !isReversed ? theUt22 : theUt12);
443 if (ExtPLin.IsDone())
445 mySqDist.Append(theSqDist);
449 myIsParallel = Standard_False;
455 if (aType1 == GeomAbs_Line)
459 const Standard_Real isFirstInfinite = (Precision::IsInfinite(theUt11) &&
460 Precision::IsInfinite(theUt12));
461 const Standard_Real isLastInfinite = (Precision::IsInfinite(theUt21) &&
462 Precision::IsInfinite(theUt22));
464 if (isFirstInfinite || isLastInfinite)
466 // Infinite number of solution
468 mySqDist.Append(theSqDist);
472 // The range created by projection of both ends of the 1st line
473 // to the 2nd one must intersect the (native) trimmed range of
476 myIsParallel = Standard_False;
478 const gp_Lin aLin1 = myC[0]->Line();
479 const gp_Lin aLin2 = myC[1]->Line();
480 const Standard_Boolean isOpposite(aLin1.Direction().Dot(aLin2.Direction()) < 0.0);
482 Bnd_Range aRange2(theUt21, theUt22);
483 Bnd_Range aProjRng12;
485 if (Precision::IsInfinite(theUt11))
488 aProjRng12.Add(Precision::Infinite());
490 aProjRng12.Add(-Precision::Infinite());
494 const gp_Pnt aPonC1 = ElCLib::Value(theUt11, aLin1);
495 const Standard_Real aPar = ElCLib::Parameter(aLin2, aPonC1);
496 aProjRng12.Add(aPar);
499 if (Precision::IsInfinite(theUt12))
502 aProjRng12.Add(-Precision::Infinite());
504 aProjRng12.Add(Precision::Infinite());
508 const gp_Pnt aPonC1 = ElCLib::Value(theUt12, aLin1);
509 const Standard_Real aPar = ElCLib::Parameter(aLin2, aPonC1);
510 aProjRng12.Add(aPar);
513 aRange2.Common(aProjRng12);
514 if (aRange2.Delta() > Precision::Confusion())
517 mySqDist.Append(theSqDist);
518 myIsParallel = Standard_True;
520 else if (!aRange2.IsVoid())
524 // ************** aLin1
527 // *************** aLin2
530 Standard_Real aPar1 = 0.0, aPar2 = 0.0;
531 aRange2.GetBounds(aPar1, aPar2);
532 aPar2 = 0.5*(aPar1 + aPar2);
533 gp_Pnt aP = ElCLib::Value(aPar2, aLin2);
534 const Extrema_POnCurv aP2(aPar2, aP);
535 aPar1 = ElCLib::Parameter(aLin1, aP);
536 aP = ElCLib::Value(aPar1, aLin1);
537 const Extrema_POnCurv aP1(aPar1, aP);
538 mypoints.Append(aP1);
539 mypoints.Append(aP2);
540 mySqDist.Append(theSqDist);
546 // ************** aLin1
551 //Take minimal trimmed distance
552 Standard_Real aDmin, aDists[4] = {mydist11, mydist12, mydist21, mydist22};
553 Extrema_POnCurv aP1, aP2;
555 Standard_Integer i, imin = 0;
556 for (i = 1; i < 4; ++i)
558 if (aDmin > aDists[i])
566 aP1.SetValues(myInf[0], myP1f);
567 aP2.SetValues(myInf[1], myP2f);
571 aP1.SetValues(myInf[0], myP1f);
572 aP2.SetValues(mySup[1], myP2l);
576 aP1.SetValues(mySup[0], myP1l);
577 aP2.SetValues(myInf[1], myP2f);
581 aP1.SetValues(mySup[0], myP1l);
582 aP2.SetValues(mySup[1], myP2l);
585 mypoints.Append(aP1);
586 mypoints.Append(aP2);
587 mySqDist.Append(aDmin);
594 myIsParallel = Standard_False;
596 //Two arcs with ranges [U1, U2] and [V1, V2] correspondingly are
597 //considered to be parallel in the following case:
598 // The range created by projection both points U1 and U2 of the
599 // 1st circle to the 2nd one intersects either the range [V1, V2] or
600 // the range [V1-PI, V2-PI]. All ranges must be adjusted to correspond
601 // periodic range before checking of intersection.
603 const gp_Circ aWorkCirc = myC[1]->Circle();
604 const Standard_Real aPeriod = M_PI + M_PI;
607 const gp_Pnt aP12 = Extrema_CurveTool::Value (*myC[0], theUt12);
608 Extrema_CurveTool::D1 (*myC[0], theUt11, aP11, aVTg1);
610 const Bnd_Range aRange(theUt21, theUt22);
613 // Project arc of the 1st circle between points theUt11 and theUt12 to the
614 // 2nd circle. It is necessary to chose correct arc from two possible ones.
616 Standard_Real aPar1 = ElCLib::InPeriod(ElCLib::Parameter(aWorkCirc, aP11),
617 theUt21, theUt21 + aPeriod);
618 const gp_Vec aVTg2 = Extrema_CurveTool::DN (*myC[1], aPar1, 1);
620 // Check if circles have same/opposite directions
621 const Standard_Boolean isOpposite(aVTg1.Dot(aVTg2) < 0.0);
623 Standard_Real aPar2 = ElCLib::InPeriod(ElCLib::Parameter(aWorkCirc, aP12),
624 theUt21, theUt21 + aPeriod);
628 // Must be aPar2 < aPar1
629 if ((aRange.Delta() > Precision::Angular()) &&
630 ((aPar1 - aPar2) < Precision::Angular()))
637 // Must be aPar2 > aPar1
638 if ((aRange.Delta() > Precision::Angular()) &&
639 ((aPar2 - aPar1) < Precision::Angular()))
645 // Now the projection result is the range [aPar1, aPar2]
646 // if aPar1 < aPar2 or the range [aPar2, aPar1], otherwise.
648 Standard_Real aMinSquareDist = RealLast();
650 aProjRng1.Add(aPar1 - aPeriod);
651 aProjRng1.Add(aPar2 - aPeriod);
652 for (Standard_Integer i = 0; i < 3; i++)
654 // Repeat computation three times, shifting the range to PI on each step,
655 // to be able to find if the concentric arcs ranges are intersected in just one parameter
656 // (lower or upper boundary).
658 Bnd_Range aRng = aProjRng1;
661 //Cases are possible and processed below:
662 //1. Extrema does not exist. In this case all common ranges are VOID.
663 //2. Arcs are parallel and distance between them is equal to sqrt(theSqDist).
664 // In this case myIsParallel = TRUE definitely.
665 //3. Arcs are parallel and distance between them is equal to (sqrt(theSqDist) + R),
666 // where R is the least radius of the both circles. In this case myIsParallel flag
667 // will temporary be set to TRUE but check will be continued until less
668 // distance will be found. At that, region with the least distance can be
669 // either a local point or continuous range. In 1st case myIsParallel = FALSE and
670 // several (or single) extremas will be returned. In the 2nd one
671 // myIsParallel = TRUE and only the least distance will be returned.
672 //4. Arcs are not parallel. Then several (or single) extremas will be returned.
674 if (aRng.Delta() > Precision::Angular())
676 Standard_Real aPar = 0.0;
677 aRng.GetIntermediatePoint(0.5, aPar);
678 const gp_Pnt aPCirc2 = ElCLib::Value(aPar, aWorkCirc);
679 Extrema_ExtPElC ExtPCir(aPCirc2,
680 Extrema_CurveTool::Circle (*myC[0]),
681 Precision::Confusion(), theUt11, theUt12);
683 Standard_Real aMinSqD = ExtPCir.SquareDistance(1);
684 for (Standard_Integer anExtID = 2; anExtID <= ExtPCir.NbExt(); anExtID++)
686 aMinSqD = Min(aMinSqD, ExtPCir.SquareDistance(anExtID));
689 if (aMinSqD <= aMinSquareDist + 10.* Epsilon(1. + aMinSqD))
692 mySqDist.Append(aMinSqD);
693 myIsParallel = Standard_True;
695 const Standard_Real aDeltaSqDist = aMinSqD - theSqDist;
696 const Standard_Real aSqD = Max(aMinSqD, theSqDist);
698 // 0 <= Dist1-Dist2 <= Eps
699 // 0 <= Dist1^2 - Dist2^2 < Eps*(Dist1+Dist2)
701 //If Dist1 ~= Dist2 ==> Dist1+Dist2 ~= 2*Dist2.
703 // 0 <= Dist1^2 - Dist2^2 <= 2*Dist2*Eps
706 // (Dist1^2 - Dist2^2)^2 <= 4*Dist2^2*Eps^2
708 if (aDeltaSqDist*aDeltaSqDist < 4.0*aSqD*Precision::SquareConfusion())
710 // New solution is found
715 //Nearer solution can be found
717 else if (!aRng.IsVoid())
719 //Check cases like this:
721 // ************** aCirc1
724 // *************** aCirc2
726 Standard_Real aPar = 0.0;
727 aRng.GetIntermediatePoint(0.5, aPar);
728 const gp_Pnt aPCirc2 = ElCLib::Value(aPar, aWorkCirc);
729 const Extrema_POnCurv aP2(aPar, aPCirc2);
731 Extrema_ExtPElC ExtPCir(aPCirc2,
732 Extrema_CurveTool::Circle (*myC[0]),
733 Precision::Confusion(), theUt11, theUt12);
735 Standard_Boolean isFound = !myIsParallel;
739 //If the flag myIsParallel was set earlier then it does not mean that
740 //we have found the minimal distance. Here we check it. If there is
741 //a pair of points, which are in less distance then myIsParallel flag
742 //was unset and the algorithm will return these nearest points.
744 for (Standard_Integer anExtID = 1; anExtID <= ExtPCir.NbExt(); anExtID++)
746 if (ExtPCir.SquareDistance(anExtID) < aMinSquareDist)
748 isFound = Standard_True;
757 myIsParallel = Standard_False;
758 for (Standard_Integer anExtID = 1; anExtID <= ExtPCir.NbExt(); anExtID++)
760 mypoints.Append(ExtPCir.Point(anExtID));
761 mypoints.Append(aP2);
762 mySqDist.Append(ExtPCir.SquareDistance(anExtID));
763 aMinSquareDist = Min(aMinSquareDist, ExtPCir.SquareDistance(anExtID));
771 // ************** Cir1
776 //Take minimal trimmed distance
777 myIsParallel = Standard_False;
778 Standard_Real aDmin, aDists[4] = { mydist11, mydist12, mydist21, mydist22 };
779 Extrema_POnCurv aP1, aP2;
781 Standard_Integer k, imin = 0;
782 for (k = 1; k < 4; ++k)
784 if (aDmin > aDists[k])
790 if (aDmin <= aMinSquareDist + 10.* Epsilon(1. + aDmin))
794 aP1.SetValues(myInf[0], myP1f);
795 aP2.SetValues(myInf[1], myP2f);
799 aP1.SetValues(myInf[0], myP1f);
800 aP2.SetValues(mySup[1], myP2l);
804 aP1.SetValues(mySup[0], myP1l);
805 aP2.SetValues(myInf[1], myP2f);
809 aP1.SetValues(mySup[0], myP1l);
810 aP2.SetValues(mySup[1], myP2l);
813 mypoints.Append(aP1);
814 mypoints.Append(aP2);
815 mySqDist.Append(aDmin);
816 aMinSquareDist = Min(aMinSquareDist, aDmin);
819 aProjRng1.Shift(M_PI);
824 //=======================================================================
827 //=======================================================================
829 void Extrema_ExtCC::PrepareResults(const Extrema_ExtElC& AlgExt,
830 const Standard_Boolean theIsInverse,
831 const Standard_Real Ut11,
832 const Standard_Real Ut12,
833 const Standard_Real Ut21,
834 const Standard_Real Ut22)
836 Standard_Integer i, NbExt;
837 Standard_Real Val, U, U2;
838 Extrema_POnCurv P1, P2;
840 myDone = AlgExt.IsDone();
842 myIsParallel = AlgExt.IsParallel();
844 PrepareParallelResult(Ut11, Ut12, Ut21, Ut22, AlgExt.SquareDistance());
847 NbExt = AlgExt.NbExt();
848 for (i = 1; i <= NbExt; i++) {
849 // Verification de la validite des parametres
850 AlgExt.Points(i, P1, P2);
861 if (Extrema_CurveTool::IsPeriodic (*myC[0]))
863 U = ElCLib::InPeriod(U, Ut11, Ut11+Extrema_CurveTool::Period (*myC[0]));
865 if (Extrema_CurveTool::IsPeriodic (*myC[1]))
867 U2 = ElCLib::InPeriod(U2, Ut21, Ut21+Extrema_CurveTool::Period (*myC[1]));
870 if ((U >= Ut11 - RealEpsilon()) &&
871 (U <= Ut12 + RealEpsilon()) &&
872 (U2 >= Ut21 - RealEpsilon()) &&
873 (U2 <= Ut22 + RealEpsilon())) {
874 Val = AlgExt.SquareDistance(i);
875 mySqDist.Append(Val);
878 P1.SetValues(U, P1.Value());
879 P2.SetValues(U2, P2.Value());
884 P1.SetValues(U2, P1.Value());
885 P2.SetValues(U, P2.Value());
897 //=======================================================================
900 //=======================================================================
902 void Extrema_ExtCC::PrepareResults(const Extrema_ECC& AlgExt,
903 const Standard_Real Ut11,
904 const Standard_Real Ut12,
905 const Standard_Real Ut21,
906 const Standard_Real Ut22)
908 Standard_Integer i, NbExt;
909 Standard_Real Val, U, U2;
910 Extrema_POnCurv P1, P2;
912 myDone = AlgExt.IsDone();
915 myIsParallel = AlgExt.IsParallel();
918 PrepareParallelResult(Ut11, Ut12, Ut21, Ut22, AlgExt.SquareDistance());
922 NbExt = AlgExt.NbExt();
923 for (i = 1; i <= NbExt; i++)
925 AlgExt.Points(i, P1, P2);
929 // Check points to be into param space.
930 if (Extrema_CurveTool::IsPeriodic (*myC[0]))
932 U = ElCLib::InPeriod(U, Ut11, Ut11 + Extrema_CurveTool::Period (*myC[0]));
934 if (Extrema_CurveTool::IsPeriodic (*myC[1]))
936 U2 = ElCLib::InPeriod(U2, Ut21, Ut21 + Extrema_CurveTool::Period (*myC[1]));
939 if ((U >= Ut11 - RealEpsilon()) &&
940 (U <= Ut12 + RealEpsilon()) &&
941 (U2 >= Ut21 - RealEpsilon()) &&
942 (U2 <= Ut22 + RealEpsilon()))
944 Val = AlgExt.SquareDistance(i);
945 mySqDist.Append(Val);
946 P1.SetValues(U, P1.Value());
947 P2.SetValues(U2, P2.Value());
956 //=======================================================================
957 //function : SetSingleSolutionFlag
959 //=======================================================================
960 void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
962 myIsFindSingleSolution = theFlag;
965 //=======================================================================
966 //function : GetSingleSolutionFlag
968 //=======================================================================
969 Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
971 return myIsFindSingleSolution;