// Created on: 1995-07-18
// Created by: Modelistation
// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+#include <algorithm>
-#include <StdFail_NotDone.hxx>
-#include <math_FunctionSetRoot.hxx>
-#include <math_NewtonFunctionSetRoot.hxx>
-#include <TColStd_Array2OfInteger.hxx>
-#include <TColStd_Array2OfReal.hxx>
+#include <Extrema_GlobOptFuncCC.hxx>
+#include <math_GlobOptMin.hxx>
#include <Standard_NullObject.hxx>
#include <Standard_OutOfRange.hxx>
+#include <StdFail_NotDone.hxx>
+#include <TColStd_Array1OfReal.hxx>
#include <Precision.hxx>
+#include <NCollection_Vector.hxx>
+#include <NCollection_CellFilter.hxx>
-Extrema_GenExtCC::Extrema_GenExtCC () : myDone (Standard_False)
+// Comparator, used in std::sort.
+static Standard_Boolean comp(const gp_XY& theA,
+ const gp_XY& theB)
{
+ if (theA.X() < theB.X())
+ {
+ return Standard_True;
+ }
+ else
+ {
+ if (theA.X() == theB.X())
+ {
+ if (theA.Y() < theB.Y())
+ return Standard_True;
+ }
+ }
+
+ return Standard_False;
}
-Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
- const Curve2& C2,
- const Standard_Integer NbU,
- const Standard_Integer NbV,
- const Standard_Real TolU,
- const Standard_Real TolV) : myF (C1,C2, Min(TolU, TolV)), myDone (Standard_False)
+class Extrema_CCPointsInspector : public NCollection_CellFilter_InspectorXY
{
- SetCurveCache (1, new Cache (C1, C1.FirstParameter(), C1.LastParameter(), NbU, Standard_True));
- SetCurveCache (2, new Cache (C2, C2.FirstParameter(), C2.LastParameter(), NbV, Standard_True));
- Perform();
-}
+public:
+ typedef gp_XY Target;
+ //! Constructor; remembers the tolerance
+ Extrema_CCPointsInspector (const Standard_Real theTol)
+ {
+ myTol = theTol * theTol;
+ myIsFind = Standard_False;
+ }
+
+ void ClearFind()
+ {
+ myIsFind = Standard_False;
+ }
+
+ Standard_Boolean isFind()
+ {
+ return myIsFind;
+ }
+
+ //! Set current point to search for coincidence
+ void SetCurrent (const gp_XY& theCurPnt)
+ {
+ myCurrent = theCurPnt;
+ }
+
+ //! Implementation of inspection method
+ NCollection_CellFilter_Action Inspect (const Target& theObject)
+ {
+ gp_XY aPt = myCurrent.Subtracted(theObject);
+ const Standard_Real aSQDist = aPt.SquareModulus();
+ if(aSQDist < myTol)
+ {
+ myIsFind = Standard_True;
+ }
+ return CellFilter_Keep;
+ }
-Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1,
- const Curve2& C2,
- const Standard_Real Uinf,
- const Standard_Real Usup,
- const Standard_Real Vinf,
- const Standard_Real Vsup,
- const Standard_Integer NbU,
- const Standard_Integer NbV,
- const Standard_Real TolU,
- const Standard_Real TolV) : myF (C1,C2), myDone (Standard_False)
+private:
+ Standard_Real myTol;
+ gp_XY myCurrent;
+ Standard_Boolean myIsFind;
+};
+
+//=======================================================================
+//function : Extrema_GenExtCC
+//purpose :
+//=======================================================================
+Extrema_GenExtCC::Extrema_GenExtCC()
+: myIsFindSingleSolution(Standard_False),
+ myParallel(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
+ myLowBorder(1,2),
+ myUppBorder(1,2),
+ myDone(Standard_False)
{
- SetCurveCache (1, new Cache (C1, Uinf, Usup, NbU, Standard_True));
- SetCurveCache (2, new Cache (C2, Vinf, Vsup, NbV, Standard_True));
- Perform();
+ myC[0] = myC[1] = 0;
}
-void Extrema_GenExtCC::SetCurveCache (const Standard_Integer theRank,
- const Handle(Cache)& theCache)
+//=======================================================================
+//function : Extrema_GenExtCC
+//purpose :
+//=======================================================================
+Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
+ const Curve2& C2)
+: myIsFindSingleSolution(Standard_False),
+ myParallel(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
+ myLowBorder(1,2),
+ myUppBorder(1,2),
+ myDone(Standard_False)
{
- Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_GenExtCC::SetCurveCache()")
- myF.SetCurve (theRank, *(Curve1*)theCache->CurvePtr());
- Standard_Integer anInd = theRank - 1;
- myCache[anInd] = theCache;
+ myC[0] = (Standard_Address)&C1;
+ myC[1] = (Standard_Address)&C2;
+ myLowBorder(1) = C1.FirstParameter();
+ myLowBorder(2) = C2.FirstParameter();
+ myUppBorder(1) = C1.LastParameter();
+ myUppBorder(2) = C2.LastParameter();
}
-void Extrema_GenExtCC::SetTolerance (const Standard_Real Tol)
+//=======================================================================
+//function : Extrema_GenExtCC
+//purpose :
+//=======================================================================
+Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
+ const Curve2& C2,
+ const Standard_Real Uinf,
+ const Standard_Real Usup,
+ const Standard_Real Vinf,
+ const Standard_Real Vsup)
+: myIsFindSingleSolution(Standard_False),
+ myParallel(Standard_False),
+ myCurveMinTol(Precision::PConfusion()),
+ myLowBorder(1,2),
+ myUppBorder(1,2),
+ myDone(Standard_False)
{
- myF.SetTolerance (Tol);
+ myC[0] = (Standard_Address)&C1;
+ myC[1] = (Standard_Address)&C2;
+ myLowBorder(1) = Uinf;
+ myLowBorder(2) = Vinf;
+ myUppBorder(1) = Usup;
+ myUppBorder(2) = Vsup;
}
+//=======================================================================
+//function : SetParams
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::SetParams(const Curve1& C1,
+ const Curve2& C2,
+ const Standard_Real Uinf,
+ const Standard_Real Usup,
+ const Standard_Real Vinf,
+ const Standard_Real Vsup)
+{
+ myC[0] = (Standard_Address)&C1;
+ myC[1] = (Standard_Address)&C2;
+ myLowBorder(1) = Uinf;
+ myLowBorder(2) = Vinf;
+ myUppBorder(1) = Usup;
+ myUppBorder(2) = Vsup;
+}
-//=============================================================================
-void Extrema_GenExtCC::Perform ()
-/*-----------------------------------------------------------------------------
-Fonction:
- Recherche de toutes les distances extremales entre les courbes C1 et C2.
- a partir de 2 echantillonnages (NbU,NbV).
-
-Methode:
- L'algorithme part de l'hypothese que les echantillonnages sont suffisamment
- fins pour que, s'il existe N distances extremales entre les 2 courbes,
- alors il existe aussi N extrema entre les 2 ensembles de points.
- Ainsi, l'algorithme consiste a partir des extrema des echantillons
- pour trouver les extrema des courbes.
- Les extrema sont calcules par l'algorithme math_FunctionSetRoot avec les
- arguments suivants:
- - myF: Extrema_FuncExtCC cree a partir de C1 et C2,
- - UV: math_Vector dont les composantes sont les parametres des points de
- l'extremum sur les ensembles de points,
- - Tol: Min(TolU,TolV), (Prov.:math_FunctionSetRoot n'autorise pas un vecteur)
- - UVinf: math_Vector dont les composantes sont les bornes inferieures de u et
- v,
- - UVsup: math_Vector dont les composantes sont les bornes superieures de u et
- v.
-
-Traitement:
- a- Constitution du tableau des square distances (TbDist2(0,NbU+1,0,NbV+1)):
- Le tableau est volontairement etendu; les lignes 0 et NbU+1 et les
- colonnes 0 et NbV+1 seront initialisees a RealFirst() ou RealLast()
- pour simplifier les tests effectues dans l'etape b
- (on n'a pas besoin de tester si le point est sur une extremite).
- b- Calcul des extrema:
- On recherche d'abord les minima et ensuite les maxima. Ces 2 traitements
- se passent de facon similaire:
- b.a- Initialisations:
- - des 'bords' du tableau TbDist2 (a RealLast() dans le cas des minima
- et a RealLast() dans le cas des maxima),
- - du tableau TbSel(0,NbU+1,0,NbV+1) de selection des points pour un
- calcul d'extremum local (a 0). Lorsqu'un couple de points sera
- selectionne, il ne sera plus selectionnable, ainsi que les couples
- adjacents (8 au maximum).
- Les adresses correspondantes seront mises a 1.
- b.b- Calcul des minima (ou maxima):
- On boucle sur toutes les square distances du tableau TbDist2:
- - recherche d'un minimum (ou maximum) sur les echantillons,
- - calcul de l'extremum sur les courbes,
- - mise a jour du tableau TbSel.
------------------------------------------------------------------------------*/
+//=======================================================================
+//function : SetTolerance
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
+{
+ myCurveMinTol = theTol;
+}
+
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::Perform()
{
myDone = Standard_False;
+ myParallel = Standard_False;
- const Handle(Cache)& aCache1 = myCache[0];
- const Handle(Cache)& aCache2 = myCache[1];
- Standard_NullObject_Raise_if ((aCache1.IsNull() || aCache2.IsNull()),
- "Extrema_GenExtCC::Perform()")
-
- Standard_Integer aNbU = aCache1->NbSamples(), aNbV = aCache2->NbSamples();
- Standard_OutOfRange_Raise_if ((aNbU < 2 ||aNbV < 2), "Extrema_GenExtCC::Perform()")
-
-/*
-a- Constitution du tableau des distances (TbDist2(0,NbU+1,0,NbV+1)):
- ---------------------------------------------------------------
-*/
-
- //ensure that caches have been calculated
- if (!aCache1->IsValid())
- aCache1->CalculatePoints();
- if (!aCache2->IsValid())
- aCache2->CalculatePoints();
-
-// Calcul des distances
- const Curve1& aCurve1 = *((Curve1*)(myF.CurvePtr (1)));
- const Curve2& aCurve2 = *((Curve1*)(myF.CurvePtr (2)));
- const Handle(ArrayOfPnt)& aPntArray1 = aCache1->Points();
- const Handle(ArrayOfPnt)& aPntArray2 = aCache2->Points();
- Standard_Integer NoU, NoV;
- TColStd_Array2OfReal TbDist2(0, aNbU + 1, 0, aNbV + 1);
- for (NoU = 1; NoU <= aNbU; NoU++) {
- const Pnt& P1 = aPntArray1->Value (NoU);
- for (NoV = 1; NoV <= aNbV; NoV++) {
- const Pnt& P2 = aPntArray2->Value (NoV);
- TbDist2(NoU,NoV) = P1.SquareDistance(P2);
- }
+ Curve1 &C1 = *(Curve1*)myC[0];
+ Curve2 &C2 = *(Curve2*)myC[1];
+
+ Standard_Integer aNbInter[2];
+ GeomAbs_Shape aContinuity = GeomAbs_C2;
+ aNbInter[0] = C1.NbIntervals(aContinuity);
+ aNbInter[1] = C2.NbIntervals(aContinuity);
+
+ if (aNbInter[0] * aNbInter[1] > 100)
+ {
+ aContinuity = GeomAbs_C1;
+ aNbInter[0] = C1.NbIntervals(aContinuity);
+ aNbInter[1] = C2.NbIntervals(aContinuity);
}
-/*
-b- Calcul des minima:
- -----------------
- b.a) Initialisations:
-*/
-// - generales
- math_Vector Tol(1, 2);
- Tol(1) = myF.Tolerance();
- Tol(2) = myF.Tolerance();
- math_Vector UV(1,2), UVinf(1,2), UVsup(1,2);
- UVinf(1) = aCache1->TrimFirstParameter();
- UVinf(2) = aCache2->TrimFirstParameter();
- UVsup(1) = aCache1->TrimLastParameter();
- UVsup(2) = aCache2->TrimLastParameter();
-
- myF.SubIntervalInitialize(UVinf,UVsup);
-
-// - des 'bords' du tableau TbDist2
- for (NoV = 0; NoV <= aNbV+1; NoV++) {
- TbDist2(0,NoV) = RealLast();
- TbDist2(aNbU+1,NoV) = RealLast();
+ TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
+ TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
+ C1.Intervals(anIntervals1, aContinuity);
+ C2.Intervals(anIntervals2, aContinuity);
+
+ // Lipchitz constant computation.
+ Standard_Real aLC = 9.0; // Default value.
+ const Standard_Real aMaxDer1 = 1.0 / C1.Resolution(1.0);
+ const Standard_Real aMaxDer2 = 1.0 / C2.Resolution(1.0);
+ const Standard_Real aMaxDer = Max(aMaxDer1, aMaxDer2) * Sqrt(2.0);
+ if (aLC > aMaxDer)
+ aLC = aMaxDer;
+
+ // Change constant value according to the concrete curve types.
+ Standard_Boolean isConstLockedFlag = Standard_False;
+ if (C1.GetType() == GeomAbs_Line)
+ {
+ Standard_Real aMaxDer = 1.0 / C2.Resolution(1.0);
+ if (aLC > aMaxDer)
+ {
+ isConstLockedFlag = Standard_True;
+ aLC = aMaxDer;
+ }
}
- for (NoU = 1; NoU <= aNbU; NoU++) {
- TbDist2(NoU,0) = RealLast();
- TbDist2(NoU,aNbV+1) = RealLast();
+ if (C2.GetType() == GeomAbs_Line)
+ {
+ Standard_Real aMaxDer = 1.0 / C1.Resolution(1.0);
+ if (aLC > aMaxDer)
+ {
+ isConstLockedFlag = Standard_True;
+ aLC = aMaxDer;
+ }
}
-// - du tableau TbSel(0,aNbU+1,0,aNbV+1) de selection des points
- TColStd_Array2OfInteger TbSel(0,aNbU+1,0,aNbV+1);
- TbSel.Init(0);
-
-/*
- b.b) Calcul des minima:
-*/
-// - recherche d un minimum sur la grille
- Standard_Integer Nu, Nv;
- Standard_Real Dist2;
- const Handle(TColStd_HArray1OfReal)& aParamArray1 = aCache1->Parameters();
- const Handle(TColStd_HArray1OfReal)& aParamArray2 = aCache2->Parameters();
- for (NoU = 1; NoU <= aNbU; NoU++) {
- for (NoV = 1; NoV <= aNbV; NoV++) {
- if (TbSel(NoU,NoV) == 0) {
- Dist2 = TbDist2(NoU,NoV);
- if ((TbDist2(NoU-1,NoV-1) >= Dist2) &&
- (TbDist2(NoU-1,NoV ) >= Dist2) &&
- (TbDist2(NoU-1,NoV+1) >= Dist2) &&
- (TbDist2(NoU ,NoV-1) >= Dist2) &&
- (TbDist2(NoU ,NoV+1) >= Dist2) &&
- (TbDist2(NoU+1,NoV-1) >= Dist2) &&
- (TbDist2(NoU+1,NoV ) >= Dist2) &&
- (TbDist2(NoU+1,NoV+1) >= Dist2)) {
-
-// - calcul de l extremum sur la surface:
-
- UV(1) = aParamArray1->Value(NoU);
- UV(2) = aParamArray2->Value(NoV);
-
- math_FunctionSetRoot S (myF,UV,Tol,UVinf,UVsup);
-
-
-// - mise a jour du tableau TbSel
- for (Nu = NoU-1; Nu <= NoU+1; Nu++) {
- for (Nv = NoV-1; Nv <= NoV+1; Nv++) {
- TbSel(Nu,Nv) = 1;
- }
- }
- }
- } // if (TbSel(NoU,NoV)
- } // for (NoV = 1; ...
- } // for (NoU = 1; ...
-/*
-c- Calcul des maxima:
- -----------------
- c.a) Initialisations:
-*/
-// - des 'bords' du tableau TbDist2
- for (NoV = 0; NoV <= aNbV+1; NoV++) {
- TbDist2(0,NoV) = RealFirst();
- TbDist2(aNbU+1,NoV) = RealFirst();
+ Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
+ math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
+ aFinder.SetLipConstState(isConstLockedFlag);
+ aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
+ Standard_Real aDiscTol = 1.0e-2;
+ Standard_Real aValueTol = 1.0e-2;
+ Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
+ aFinder.SetTol(aDiscTol, aSameTol);
+ aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
+
+ // Size computed to have cell index inside of int32 value.
+ const Standard_Real aCellSize = Max(anIntervals1.Upper() - anIntervals1.Lower(),
+ anIntervals2.Upper() - anIntervals2.Lower())
+ * Precision::PConfusion() / (2.0 * Sqrt(2.0));
+ Extrema_CCPointsInspector anInspector(Precision::PConfusion());
+ NCollection_CellFilter<Extrema_CCPointsInspector> aFilter(aCellSize);
+ NCollection_Vector<gp_XY> aPnts;
+
+ Standard_Integer i,j,k;
+ math_Vector aFirstBorderInterval(1,2);
+ math_Vector aSecondBorderInterval(1,2);
+ Standard_Real aF = RealLast(); // Best functional value.
+ Standard_Real aCurrF = RealLast(); // Current functional value computed on current interval.
+ for(i = 1; i <= aNbInter[0]; i++)
+ {
+ for(j = 1; j <= aNbInter[1]; j++)
+ {
+ aFirstBorderInterval(1) = anIntervals1(i);
+ aFirstBorderInterval(2) = anIntervals2(j);
+ aSecondBorderInterval(1) = anIntervals1(i + 1);
+ aSecondBorderInterval(2) = anIntervals2(j + 1);
+
+ aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
+ aFinder.Perform(GetSingleSolutionFlag());
+
+ // Check that solution found on current interval is not worse than previous.
+ aCurrF = aFinder.GetF();
+ if (aCurrF >= aF + aSameTol * aValueTol)
+ {
+ continue;
+ }
+
+ // Clean previously computed solution if current one is better.
+ if (aCurrF > aF - aSameTol * aValueTol)
+ {
+ if (aCurrF < aF)
+ aF = aCurrF;
+ }
+ else
+ {
+ aF = aCurrF;
+ aFilter.Reset(aCellSize);
+ aPnts.Clear();
+ }
+
+ // Save found solutions avoiding repetitions.
+ math_Vector sol(1,2);
+ for(k = 1; k <= aFinder.NbExtrema(); k++)
+ {
+ aFinder.Points(k, sol);
+ gp_XY aPnt2d(sol(1), sol(2));
+
+ gp_XY aXYmin = anInspector.Shift(aPnt2d, -aCellSize);
+ gp_XY aXYmax = anInspector.Shift(aPnt2d, aCellSize);
+
+ anInspector.ClearFind();
+ anInspector.SetCurrent(aPnt2d);
+ aFilter.Inspect(aXYmin, aXYmax, anInspector);
+ if (!anInspector.isFind())
+ {
+ // Point is out of close cells, add new one.
+ aFilter.Add(aPnt2d, aPnt2d);
+ aPnts.Append(gp_XY(sol(1), sol(2)));
+ }
+ }
+ }
}
- for (NoU = 1; NoU <= aNbU; NoU++) {
- TbDist2(NoU,0) = RealFirst();
- TbDist2(NoU,aNbV+1) = RealFirst();
+
+ if (aPnts.Size() == 0)
+ {
+ // No solutions.
+ myDone = Standard_False;
+ return;
}
-// - du tableau TbSel(0,aNbU+1,0,aNbV+1) de selection des points
- TbSel.Init(0);
- /*for (NoU = 0; NoU <= aNbU+1; NoU++) {
- for (NoV = 0; NoV <= aNbV+1; NoV++) {
- TbSel(NoU,NoV) = 0;
+ // Check for infinity solutions case, for this:
+ // Sort points lexicographically and check midpoint between each two neighboring points.
+ // If all midpoints functional value is acceptable
+ // then set myParallel flag to true and return one solution.
+ std::sort(aPnts.begin(), aPnts.end(), comp);
+ Standard_Boolean isParallel = Standard_False;
+ Standard_Real aVal = 0.0;
+ math_Vector aVec(1,2, 0.0);
+
+ // Avoid mark parallel case when have duplicates out of tolerance.
+ // Bad conditioned task: bug25635_1, bug23706_10, bug23706_13.
+ const Standard_Integer aMinNbInfSol = 100;
+ if (aPnts.Size() >= aMinNbInfSol)
+ {
+ isParallel = Standard_True;
+ for(Standard_Integer anIdx = aPnts.Lower(); anIdx <= aPnts.Upper() - 1; anIdx++)
+ {
+ const gp_XY& aCurrent = aPnts(anIdx);
+ const gp_XY& aNext = aPnts(anIdx + 1);
+
+ aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
+ aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
+
+ aFunc.Value(aVec, aVal);
+
+ if (Abs(aVal - aF) > Precision::Confusion())
+ {
+ isParallel = Standard_False;
+ break;
+ }
+ }
+ }
+
+ if (isParallel)
+ {
+ const gp_XY& aCurrent = aPnts.First();
+ myPoints1.Append(aCurrent.X());
+ myPoints2.Append(aCurrent.Y());
+ myParallel = Standard_True;
+ }
+ else
+ {
+ for(Standard_Integer anIdx = aPnts.Lower(); anIdx <= aPnts.Upper(); anIdx++)
+ {
+ const gp_XY& aCurrent = aPnts(anIdx);
+ myPoints1.Append(aCurrent.X());
+ myPoints2.Append(aCurrent.Y());
}
- }*/
-/*
- c.b) Calcul des maxima:
-*/
-// - recherche d un maximum sur la grille
- for (NoU = 1; NoU <= aNbU; NoU++) {
- for (NoV = 1; NoV <= aNbV; NoV++) {
- if (TbSel(NoU,NoV) == 0) {
- Dist2 = TbDist2(NoU,NoV);
- if ((TbDist2(NoU-1,NoV-1) <= Dist2) &&
- (TbDist2(NoU-1,NoV ) <= Dist2) &&
- (TbDist2(NoU-1,NoV+1) <= Dist2) &&
- (TbDist2(NoU ,NoV-1) <= Dist2) &&
- (TbDist2(NoU ,NoV+1) <= Dist2) &&
- (TbDist2(NoU+1,NoV-1) <= Dist2) &&
- (TbDist2(NoU+1,NoV ) <= Dist2) &&
- (TbDist2(NoU+1,NoV+1) <= Dist2)) {
-
-// - calcul de l extremum sur la surface:
-
- UV(1) = aParamArray1->Value(NoU);
- UV(2) = aParamArray2->Value(NoV);
-
- math_FunctionSetRoot S (myF,UV,Tol,UVinf,UVsup);
-
-// - mise a jour du tableau TbSel
- for (Nu = NoU-1; Nu <= NoU+1; Nu++) {
- for (Nv = NoV-1; Nv <= NoV+1; Nv++) {
- TbSel(Nu,Nv) = 1;
- }
- }
- }
- } // if (TbSel(NoU,NoV))
- } // for (NoV = 1; ...)
- } // for (NoU = 1; ...)
+ }
+
myDone = Standard_True;
}
-//=============================================================================
-Standard_Boolean Extrema_GenExtCC::IsDone () const { return myDone; }
-//=============================================================================
+//=======================================================================
+//function : IsDone
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::IsDone() const
+{
+ return myDone;
+}
-Standard_Integer Extrema_GenExtCC::NbExt () const
+//=======================================================================
+//function : IsParallel
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::IsParallel() const
+{
+ return myParallel;
+}
+
+//=======================================================================
+//function : NbExt
+//purpose :
+//=======================================================================
+Standard_Integer Extrema_GenExtCC::NbExt() const
{
StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::NbExt()")
- return myF.NbExt();
+
+ return myPoints1.Length();
}
-//=============================================================================
-Standard_Real Extrema_GenExtCC::SquareDistance (const Standard_Integer N) const
+//=======================================================================
+//function : SquareDistance
+//purpose :
+//=======================================================================
+Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
{
StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()")
Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()")
- return myF.SquareDistance(N);
+
+ return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
}
-//=============================================================================
-void Extrema_GenExtCC::Points (const Standard_Integer N,
- POnC& P1, POnC& P2) const
+//=======================================================================
+//function : Points
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::Points(const Standard_Integer N,
+ POnC& P1,
+ POnC& P2) const
{
- StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()")
- Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()")
- myF.Points(N,P1,P2);
+ StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::Points()")
+ Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::Points()")
+
+ P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
+ P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
+}
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose :
+//=======================================================================
+void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+ myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose :
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
+{
+ return myIsFindSingleSolution;
}