Warning, /include/opencascade/Extrema_GenExtCC.gxx is written in an unsupported language. File is not indexed.
0001 // Created on: 1995-07-18
0002 // Created by: Modelistation
0003 // Copyright (c) 1995-1999 Matra Datavision
0004 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0005 //
0006 // This file is part of Open CASCADE Technology software library.
0007 //
0008 // This library is free software; you can redistribute it and/or modify it under
0009 // the terms of the GNU Lesser General Public License version 2.1 as published
0010 // by the Free Software Foundation, with special exception defined in the file
0011 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0012 // distribution for complete text of the license and disclaimer of any warranty.
0013 //
0014 // Alternatively, this file may be used under the terms of Open CASCADE
0015 // commercial license or contractual agreement.
0016
0017 #include <algorithm>
0018
0019 #include <Extrema_GlobOptFuncCC.hxx>
0020 #include <math_GlobOptMin.hxx>
0021 #include <Standard_NullObject.hxx>
0022 #include <Standard_OutOfRange.hxx>
0023 #include <StdFail_NotDone.hxx>
0024 #include <TColStd_Array1OfReal.hxx>
0025 #include <TColStd_ListOfInteger.hxx>
0026 #include <Precision.hxx>
0027 #include <NCollection_Vector.hxx>
0028 #include <NCollection_CellFilter.hxx>
0029 #include <GCPnts_AbscissaPoint.hxx>
0030
0031 // Comparator, used in std::sort.
0032 static Standard_Boolean comp(const gp_XY& theA,
0033 const gp_XY& theB)
0034 {
0035 if (theA.X() < theB.X())
0036 {
0037 return Standard_True;
0038 }
0039 else
0040 {
0041 if (theA.X() == theB.X())
0042 {
0043 if (theA.Y() < theB.Y())
0044 return Standard_True;
0045 }
0046 }
0047
0048 return Standard_False;
0049 }
0050
0051 static void ChangeIntervals(Handle(TColStd_HArray1OfReal)& theInts, const Standard_Integer theNbInts)
0052 {
0053 Standard_Integer aNbInts = theInts->Length() - 1;
0054 Standard_Integer aNbAdd = theNbInts - aNbInts;
0055 Handle(TColStd_HArray1OfReal) aNewInts = new TColStd_HArray1OfReal(1, theNbInts + 1);
0056 Standard_Integer aNbLast = theInts->Length();
0057 Standard_Integer i;
0058 if (aNbInts == 1)
0059 {
0060 aNewInts->SetValue(1, theInts->First());
0061 aNewInts->SetValue(theNbInts + 1, theInts->Last());
0062 Standard_Real dt = (theInts->Last() - theInts->First()) / theNbInts;
0063 Standard_Real t = theInts->First() + dt;
0064 for (i = 2; i <= theNbInts; ++i, t += dt)
0065 {
0066 aNewInts->SetValue(i, t);
0067 }
0068 theInts = aNewInts;
0069 return;
0070 }
0071 //
0072 for (i = 1; i <= aNbLast; ++i)
0073 {
0074 aNewInts->SetValue(i, theInts->Value(i));
0075 }
0076 //
0077 while (aNbAdd > 0)
0078 {
0079 Standard_Real anLIntMax = -1.;
0080 Standard_Integer aMaxInd = -1;
0081 for (i = 1; i < aNbLast; ++i)
0082 {
0083 Standard_Real anL = aNewInts->Value(i + 1) - aNewInts->Value(i);
0084 if (anL > anLIntMax)
0085 {
0086 anLIntMax = anL;
0087 aMaxInd = i;
0088 }
0089 }
0090
0091 Standard_Real t = (aNewInts->Value(aMaxInd + 1) + aNewInts->Value(aMaxInd)) / 2.;
0092 for (i = aNbLast; i > aMaxInd; --i)
0093 {
0094 aNewInts->SetValue(i + 1, aNewInts->Value(i));
0095 }
0096 aNbLast++;
0097 aNbAdd--;
0098 aNewInts->SetValue(aMaxInd + 1, t);
0099 }
0100 theInts = aNewInts;
0101 }
0102 class Extrema_CCPointsInspector : public NCollection_CellFilter_InspectorXY
0103 {
0104 public:
0105 typedef gp_XY Target;
0106 //! Constructor; remembers the tolerance
0107 Extrema_CCPointsInspector (const Standard_Real theTol)
0108 {
0109 myTol = theTol * theTol;
0110 myIsFind = Standard_False;
0111 }
0112
0113 void ClearFind()
0114 {
0115 myIsFind = Standard_False;
0116 }
0117
0118 Standard_Boolean isFind()
0119 {
0120 return myIsFind;
0121 }
0122
0123 //! Set current point to search for coincidence
0124 void SetCurrent (const gp_XY& theCurPnt)
0125 {
0126 myCurrent = theCurPnt;
0127 }
0128
0129 //! Implementation of inspection method
0130 NCollection_CellFilter_Action Inspect (const Target& theObject)
0131 {
0132 gp_XY aPt = myCurrent.Subtracted(theObject);
0133 const Standard_Real aSQDist = aPt.SquareModulus();
0134 if(aSQDist < myTol)
0135 {
0136 myIsFind = Standard_True;
0137 }
0138
0139 return CellFilter_Keep;
0140 }
0141
0142 private:
0143 Standard_Real myTol;
0144 gp_XY myCurrent;
0145 Standard_Boolean myIsFind;
0146 };
0147
0148 //=======================================================================
0149 //function : ProjPOnC
0150 //purpose : Projects the point on the curve and returns the minimal
0151 // projection distance
0152 //=======================================================================
0153 static Standard_Real ProjPOnC(const Pnt& theP,
0154 Extrema_GExtPC& theProjTool)
0155 {
0156 Standard_Real aDist = ::RealLast();
0157 theProjTool.Perform(theP);
0158 if (theProjTool.IsDone() && theProjTool.NbExt())
0159 {
0160 for (Standard_Integer i = 1; i <= theProjTool.NbExt(); ++i)
0161 {
0162 Standard_Real aD = theProjTool.SquareDistance(i);
0163 if (aD < aDist)
0164 aDist = aD;
0165 }
0166 }
0167 return aDist;
0168 }
0169
0170 //=======================================================================
0171 //function : Extrema_GenExtCC
0172 //purpose :
0173 //=======================================================================
0174 Extrema_GenExtCC::Extrema_GenExtCC()
0175 : myIsFindSingleSolution(Standard_False),
0176 myParallel(Standard_False),
0177 myCurveMinTol(Precision::PConfusion()),
0178 myLowBorder(1,2),
0179 myUppBorder(1,2),
0180 myDone(Standard_False)
0181 {
0182 myC[0] = myC[1] = 0;
0183 }
0184
0185 //=======================================================================
0186 //function : Extrema_GenExtCC
0187 //purpose :
0188 //=======================================================================
0189 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
0190 const Curve2& C2)
0191 : myIsFindSingleSolution(Standard_False),
0192 myParallel(Standard_False),
0193 myCurveMinTol(Precision::PConfusion()),
0194 myLowBorder(1,2),
0195 myUppBorder(1,2),
0196 myDone(Standard_False)
0197 {
0198 myC[0] = (Standard_Address)&C1;
0199 myC[1] = (Standard_Address)&C2;
0200 myLowBorder(1) = C1.FirstParameter();
0201 myLowBorder(2) = C2.FirstParameter();
0202 myUppBorder(1) = C1.LastParameter();
0203 myUppBorder(2) = C2.LastParameter();
0204 }
0205
0206 //=======================================================================
0207 //function : Extrema_GenExtCC
0208 //purpose :
0209 //=======================================================================
0210 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
0211 const Curve2& C2,
0212 const Standard_Real Uinf,
0213 const Standard_Real Usup,
0214 const Standard_Real Vinf,
0215 const Standard_Real Vsup)
0216 : myIsFindSingleSolution(Standard_False),
0217 myParallel(Standard_False),
0218 myCurveMinTol(Precision::PConfusion()),
0219 myLowBorder(1,2),
0220 myUppBorder(1,2),
0221 myDone(Standard_False)
0222 {
0223 myC[0] = (Standard_Address)&C1;
0224 myC[1] = (Standard_Address)&C2;
0225 myLowBorder(1) = Uinf;
0226 myLowBorder(2) = Vinf;
0227 myUppBorder(1) = Usup;
0228 myUppBorder(2) = Vsup;
0229 }
0230
0231 //=======================================================================
0232 //function : SetParams
0233 //purpose :
0234 //=======================================================================
0235 void Extrema_GenExtCC::SetParams(const Curve1& C1,
0236 const Curve2& C2,
0237 const Standard_Real Uinf,
0238 const Standard_Real Usup,
0239 const Standard_Real Vinf,
0240 const Standard_Real Vsup)
0241 {
0242 myC[0] = (Standard_Address)&C1;
0243 myC[1] = (Standard_Address)&C2;
0244 myLowBorder(1) = Uinf;
0245 myLowBorder(2) = Vinf;
0246 myUppBorder(1) = Usup;
0247 myUppBorder(2) = Vsup;
0248 }
0249
0250 //=======================================================================
0251 //function : SetTolerance
0252 //purpose :
0253 //=======================================================================
0254 void Extrema_GenExtCC::SetTolerance(Standard_Real theTol)
0255 {
0256 myCurveMinTol = theTol;
0257 }
0258
0259 //=======================================================================
0260 //function : Perform
0261 //purpose :
0262 //=======================================================================
0263 void Extrema_GenExtCC::Perform()
0264 {
0265 myDone = Standard_False;
0266 myParallel = Standard_False;
0267
0268 Curve1 &C1 = *(Curve1*)myC[0];
0269 Curve2 &C2 = *(Curve2*)myC[1];
0270
0271 Standard_Integer aNbInter[2];
0272 GeomAbs_Shape aContinuity = GeomAbs_C2;
0273 aNbInter[0] = C1.NbIntervals(aContinuity);
0274 aNbInter[1] = C2.NbIntervals(aContinuity);
0275
0276 if (aNbInter[0] * aNbInter[1] > 100)
0277 {
0278 aContinuity = GeomAbs_C1;
0279 aNbInter[0] = C1.NbIntervals(aContinuity);
0280 aNbInter[1] = C2.NbIntervals(aContinuity);
0281 }
0282
0283 Standard_Real anL[2];
0284 Standard_Integer indmax = -1, indmin = -1;
0285 const Standard_Real mult = 20.;
0286 if (!(Precision::IsInfinite(C1.FirstParameter()) || Precision::IsInfinite(C1.LastParameter()) ||
0287 Precision::IsInfinite(C2.FirstParameter()) || Precision::IsInfinite(C2.LastParameter())))
0288 {
0289 anL[0] = GCPnts_AbscissaPoint::Length(C1);
0290 anL[1] = GCPnts_AbscissaPoint::Length(C2);
0291 if (anL[0] / aNbInter[0] > mult * anL[1] / aNbInter[1])
0292 {
0293 indmax = 0;
0294 indmin = 1;
0295 }
0296 else if (anL[1] / aNbInter[1] > mult * anL[0] / aNbInter[0])
0297 {
0298 indmax = 1;
0299 indmin = 0;
0300 }
0301 }
0302 Standard_Integer aNbIntOpt = 0;
0303 if (indmax >= 0)
0304 {
0305 aNbIntOpt = RealToInt(anL[indmax] * aNbInter[indmin] / anL[indmin] / (mult / 4.)) + 1;
0306 if (aNbIntOpt > 100 || aNbIntOpt < aNbInter[indmax])
0307 {
0308 indmax = -1;
0309 }
0310 else
0311 {
0312 if (aNbIntOpt * aNbInter[indmin] > 100)
0313 {
0314 aNbIntOpt = 100 / aNbInter[indmin];
0315 if (aNbIntOpt < aNbInter[indmax])
0316 {
0317 indmax = -1;
0318 }
0319 }
0320 }
0321 }
0322
0323 Handle(TColStd_HArray1OfReal) anIntervals1 = new TColStd_HArray1OfReal(1, aNbInter[0] + 1);
0324 Handle(TColStd_HArray1OfReal) anIntervals2 = new TColStd_HArray1OfReal(1, aNbInter[1] + 1);
0325 C1.Intervals(anIntervals1->ChangeArray1(), aContinuity);
0326 C2.Intervals(anIntervals2->ChangeArray1(), aContinuity);
0327 if (indmax >= 0)
0328 {
0329 if (indmax == 0)
0330 {
0331 //Change anIntervals1
0332 ChangeIntervals(anIntervals1, aNbIntOpt);
0333 aNbInter[0] = anIntervals1->Length() - 1;
0334 }
0335 else
0336 {
0337 //Change anIntervals2;
0338 ChangeIntervals(anIntervals2, aNbIntOpt);
0339 aNbInter[1] = anIntervals2->Length() - 1;
0340 }
0341 }
0342 if (C1.IsClosed() && aNbInter[0] == 1)
0343 {
0344 ChangeIntervals(anIntervals1, 3);
0345 aNbInter[0] = anIntervals1->Length() - 1;
0346 }
0347 if (C2.IsClosed() && aNbInter[1] == 1)
0348 {
0349 ChangeIntervals(anIntervals2, 3);
0350 aNbInter[1] = anIntervals2->Length() - 1;
0351 }
0352
0353 // Lipchitz constant computation.
0354 const Standard_Real aMaxLC = 10000.;
0355 Standard_Real aLC = 100.0; // Default value.
0356 const Standard_Real aMaxDer1 = 1.0 / C1.Resolution(1.0);
0357 const Standard_Real aMaxDer2 = 1.0 / C2.Resolution(1.0);
0358 Standard_Real aMaxDer = Max(aMaxDer1, aMaxDer2) * Sqrt(2.0);
0359 if (aLC > aMaxDer)
0360 aLC = aMaxDer;
0361
0362 // Change constant value according to the concrete curve types.
0363 Standard_Boolean isConstLockedFlag = Standard_False;
0364 //To prevent LipConst to became too small
0365 const Standard_Real aCR = 0.001;
0366 if (aMaxDer1 / aMaxDer < aCR || aMaxDer2 / aMaxDer < aCR)
0367 {
0368 isConstLockedFlag = Standard_True;
0369 }
0370 if (aMaxDer > aMaxLC)
0371 {
0372 aLC = aMaxLC;
0373 isConstLockedFlag = Standard_True;
0374 }
0375 if (C1.GetType() == GeomAbs_Line)
0376 {
0377 aMaxDer = 1.0 / C2.Resolution(1.0);
0378 if (aLC > aMaxDer)
0379 {
0380 isConstLockedFlag = Standard_True;
0381 aLC = aMaxDer;
0382 }
0383 }
0384 if (C2.GetType() == GeomAbs_Line)
0385 {
0386 aMaxDer = 1.0 / C1.Resolution(1.0);
0387 if (aLC > aMaxDer)
0388 {
0389 isConstLockedFlag = Standard_True;
0390 aLC = aMaxDer;
0391 }
0392 }
0393
0394 Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
0395 if (aLC < aMaxLC || aMaxDer > aMaxLC)
0396 {
0397 //Estimation of Lipschitz constant by gradient of optimization function
0398 //using sampling in parameter space.
0399 math_Vector aT(1, 2), aG(1, 2);
0400 Standard_Real aF, aMaxG = 0.;
0401 Standard_Real t1, t2, dt1, dt2;
0402 Standard_Integer n1 = 21, n2 = 21, i1, i2;
0403 dt1 = (C1.LastParameter() - C1.FirstParameter()) / (n1 - 1);
0404 dt2 = (C2.LastParameter() - C2.FirstParameter()) / (n2 - 1);
0405 for (i1 = 1, t1 = C1.FirstParameter(); i1 <= n1; ++i1, t1 += dt1)
0406 {
0407 aT(1) = t1;
0408 for (i2 = 1, t2 = C2.FirstParameter(); i2 <= n2; ++i2, t2 += dt2)
0409 {
0410 aT(2) = t2;
0411 aFunc.Values(aT, aF, aG);
0412 Standard_Real aMod = aG(1)*aG(1) + aG(2)*aG(2);
0413 aMaxG = Max(aMaxG, aMod);
0414 }
0415 }
0416 aMaxG = Sqrt(aMaxG);
0417 if (aMaxG > aMaxDer)
0418 {
0419 aLC = Min(aMaxG, aMaxLC);
0420 isConstLockedFlag = Standard_True;
0421 }
0422 if (aMaxG > 100. * aMaxLC)
0423 {
0424 aLC = 100. * aMaxLC;
0425 isConstLockedFlag = Standard_True;
0426 }
0427 else if (aMaxG < 0.1 * aMaxDer)
0428 {
0429 isConstLockedFlag = Standard_True;
0430 }
0431 }
0432 math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder, aLC);
0433 aFinder.SetLipConstState(isConstLockedFlag);
0434 aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
0435 Standard_Real aDiscTol = 1.0e-2;
0436 Standard_Real aValueTol = 1.0e-2;
0437 Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
0438 aFinder.SetTol(aDiscTol, aSameTol);
0439 aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
0440
0441 // Size computed to have cell index inside of int32 value.
0442 const Standard_Real aCellSize = Max(Max(anIntervals1->Last() - anIntervals1->First(),
0443 anIntervals2->Last() - anIntervals2->First())
0444 * Precision::PConfusion() / (2.0 * Sqrt(2.0)),
0445 Precision::PConfusion());
0446 Extrema_CCPointsInspector anInspector(aCellSize);
0447 NCollection_CellFilter<Extrema_CCPointsInspector> aFilter(aCellSize);
0448 NCollection_Vector<gp_XY> aPnts;
0449
0450 Standard_Integer i,j,k;
0451 math_Vector aFirstBorderInterval(1,2);
0452 math_Vector aSecondBorderInterval(1,2);
0453 Standard_Real aF = RealLast(); // Best functional value.
0454 Standard_Real aCurrF = RealLast(); // Current functional value computed on current interval.
0455 for(i = 1; i <= aNbInter[0]; i++)
0456 {
0457 for(j = 1; j <= aNbInter[1]; j++)
0458 {
0459 aFirstBorderInterval(1) = anIntervals1->Value(i);
0460 aFirstBorderInterval(2) = anIntervals2->Value(j);
0461 aSecondBorderInterval(1) = anIntervals1->Value(i + 1);
0462 aSecondBorderInterval(2) = anIntervals2->Value(j + 1);
0463
0464 aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
0465 aFinder.Perform(GetSingleSolutionFlag());
0466
0467 // Check that solution found on current interval is not worse than previous.
0468 aCurrF = aFinder.GetF();
0469 if (aCurrF >= aF + aSameTol * aValueTol)
0470 {
0471 continue;
0472 }
0473
0474 // Clean previously computed solution if current one is better.
0475 if (aCurrF > aF - aSameTol * aValueTol)
0476 {
0477 if (aCurrF < aF)
0478 aF = aCurrF;
0479 }
0480 else
0481 {
0482 aF = aCurrF;
0483 aFilter.Reset(aCellSize);
0484 aPnts.Clear();
0485 }
0486
0487 // Save found solutions avoiding repetitions.
0488 math_Vector sol(1,2);
0489 for(k = 1; k <= aFinder.NbExtrema(); k++)
0490 {
0491 aFinder.Points(k, sol);
0492 gp_XY aPnt2d(sol(1), sol(2));
0493
0494 gp_XY aXYmin = anInspector.Shift(aPnt2d, -aCellSize);
0495 gp_XY aXYmax = anInspector.Shift(aPnt2d, aCellSize);
0496
0497 anInspector.ClearFind();
0498 anInspector.SetCurrent(aPnt2d);
0499 aFilter.Inspect(aXYmin, aXYmax, anInspector);
0500 if (!anInspector.isFind())
0501 {
0502 // Point is out of close cells, add new one.
0503 aFilter.Add(aPnt2d, aPnt2d);
0504 aPnts.Append(gp_XY(sol(1), sol(2)));
0505 }
0506 }
0507 }
0508 }
0509
0510 const Standard_Integer aNbSol = aPnts.Length();
0511 if (aNbSol == 0)
0512 {
0513 // No solutions.
0514 myDone = Standard_False;
0515 return;
0516 }
0517
0518 myDone = Standard_True;
0519
0520 if (aNbSol == 1)
0521 {
0522 // Single solution
0523 const gp_XY& aSol = aPnts.First();
0524 myPoints1.Append(aSol.X());
0525 myPoints2.Append(aSol.Y());
0526 return;
0527 }
0528
0529 // More than one solution is found.
0530 // Check for infinity solutions case, for this:
0531 // Sort points lexicographically and check midpoint between each two neighboring points.
0532 // If all midpoints functional value is acceptable then check the projection distances
0533 // of the bounding points of the curves onto the opposite curves.
0534 // If these distances are also acceptable set myParallel flag to true and return one solution.
0535 std::sort(aPnts.begin(), aPnts.end(), comp);
0536
0537 // Solutions to pass into result.
0538 // If the parallel segment is found, save only extreme solutions on that segment.
0539 // The first and last solutions will always be the extreme ones, thus save them unconditionally.
0540 TColStd_ListOfInteger aSolutions;
0541
0542 // Manages the addition of the solution into result.
0543 // Set it to TRUE to add the first solution.
0544 Standard_Boolean bSaveSolution = Standard_True;
0545
0546 // Define direction of the second curve relatively the first one
0547 // (it will be needed for projection).
0548 Standard_Boolean bDirsCoinside = Standard_True;
0549 // Check also if the found solutions are not concentrated in one point
0550 // on any of the curves. And if they are, avoid marking the curves as parallel.
0551 Standard_Boolean bDifferentSolutions = Standard_False;
0552
0553 Standard_Boolean isParallel = Standard_True;
0554 Standard_Real aVal = 0.0;
0555 math_Vector aVec(1, 2, 0.0);
0556
0557 // Iterate on all solutions and collect the extreme solutions on all parallel segments.
0558 for (Standard_Integer anIdx = 0; anIdx < aNbSol - 1; anIdx++)
0559 {
0560 const gp_XY& aCurrent = aPnts(anIdx);
0561 const gp_XY& aNext = aPnts(anIdx + 1);
0562
0563 aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
0564 aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
0565
0566 aFunc.Value(aVec, aVal);
0567 if (Abs(aVal - aF) < Precision::Confusion())
0568 {
0569 // It seems the parallel segment is found.
0570 // Save only extreme solutions on that segment.
0571 if (bSaveSolution)
0572 {
0573 // Add current solution as the beginning of the parallel segment.
0574 aSolutions.Append(anIdx);
0575 // Do not keep the next solution in current parallel segment.
0576 bSaveSolution = Standard_False;
0577 }
0578 }
0579 else
0580 {
0581 // Mid point does not satisfy the tolerance criteria, curves are not parallel.
0582 isParallel = Standard_False;
0583 // Add current solution as the last one in previous parallel segment.
0584 aSolutions.Append(anIdx);
0585 // Save also the next solution as the first one in next parallel segment.
0586 bSaveSolution = Standard_True;
0587 }
0588
0589 if (!bDifferentSolutions)
0590 {
0591 if (aNext.X() > aCurrent.X())
0592 {
0593 if (aNext.Y() > aCurrent.Y())
0594 {
0595 bDifferentSolutions = Standard_True;
0596 bDirsCoinside = Standard_True;
0597 }
0598 else if (aNext.Y() < aCurrent.Y())
0599 {
0600 bDifferentSolutions = Standard_True;
0601 bDirsCoinside = Standard_False;
0602 }
0603 }
0604 }
0605 }
0606 // Save the last solution
0607 aSolutions.Append(aNbSol - 1);
0608
0609 if (!bDifferentSolutions)
0610 isParallel = Standard_False;
0611
0612 if (isParallel)
0613 {
0614 // For the check on parallel case it is also necessary to check additionally
0615 // if the ends of the curves do not diverge. For this, project the bounding
0616 // points of the curves on the opposite curves and check the distances.
0617
0618 Standard_Real aT1[2] = {myLowBorder(1), myUppBorder(1)};
0619 Standard_Real aT2[2] = {bDirsCoinside ? myLowBorder(2) : myUppBorder(2),
0620 bDirsCoinside ? myUppBorder(2) : myLowBorder(2)};
0621
0622 Extrema_GExtPC anExtPC1, anExtPC2;
0623 anExtPC1.Initialize(C1, myLowBorder(1), myUppBorder(1));
0624 anExtPC2.Initialize(C2, myLowBorder(2), myUppBorder(2));
0625
0626 for (Standard_Integer iT = 0; isParallel && (iT < 2); ++iT)
0627 {
0628 Standard_Real aDist1 = ProjPOnC(C1.Value(aT1[iT]), anExtPC2);
0629 Standard_Real aDist2 = ProjPOnC(C2.Value(aT2[iT]), anExtPC1);
0630 isParallel = (Abs(Min(aDist1, aDist2) - aF * aF) < Precision::Confusion());
0631 }
0632 }
0633
0634 if (isParallel)
0635 {
0636 // Keep only one solution
0637 const gp_XY& aSol = aPnts.First();
0638 myPoints1.Append(aSol.X());
0639 myPoints2.Append(aSol.Y());
0640 myParallel = Standard_True;
0641 }
0642 else
0643 {
0644 // Keep all saved solutions
0645 TColStd_ListIteratorOfListOfInteger aItSol(aSolutions);
0646 for (; aItSol.More(); aItSol.Next())
0647 {
0648 const gp_XY& aSol = aPnts(aItSol.Value());
0649 myPoints1.Append(aSol.X());
0650 myPoints2.Append(aSol.Y());
0651 }
0652 }
0653 }
0654
0655 //=======================================================================
0656 //function : IsDone
0657 //purpose :
0658 //=======================================================================
0659 Standard_Boolean Extrema_GenExtCC::IsDone() const
0660 {
0661 return myDone;
0662 }
0663
0664 //=======================================================================
0665 //function : IsParallel
0666 //purpose :
0667 //=======================================================================
0668 Standard_Boolean Extrema_GenExtCC::IsParallel() const
0669 {
0670 if (!IsDone()) throw StdFail_NotDone();
0671 return myParallel;
0672 }
0673
0674 //=======================================================================
0675 //function : NbExt
0676 //purpose :
0677 //=======================================================================
0678 Standard_Integer Extrema_GenExtCC::NbExt() const
0679 {
0680 if (!IsDone()) throw StdFail_NotDone();
0681 return myPoints1.Length();
0682 }
0683
0684 //=======================================================================
0685 //function : SquareDistance
0686 //purpose :
0687 //=======================================================================
0688 Standard_Real Extrema_GenExtCC::SquareDistance(const Standard_Integer N) const
0689 {
0690 if (N < 1 || N > NbExt())
0691 {
0692 throw Standard_OutOfRange();
0693 }
0694
0695 return Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)).SquareDistance(Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
0696 }
0697
0698 //=======================================================================
0699 //function : Points
0700 //purpose :
0701 //=======================================================================
0702 void Extrema_GenExtCC::Points(const Standard_Integer N,
0703 POnC& P1,
0704 POnC& P2) const
0705 {
0706 if (N < 1 || N > NbExt())
0707 {
0708 throw Standard_OutOfRange();
0709 }
0710
0711 P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
0712 P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
0713 }
0714
0715 //=======================================================================
0716 //function : SetSingleSolutionFlag
0717 //purpose :
0718 //=======================================================================
0719 void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
0720 {
0721 myIsFindSingleSolution = theFlag;
0722 }
0723
0724 //=======================================================================
0725 //function : GetSingleSolutionFlag
0726 //purpose :
0727 //=======================================================================
0728 Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
0729 {
0730 return myIsFindSingleSolution;
0731 }