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.
18 #include <Adaptor2d_Curve2d.hxx>
20 #include <Extrema_Curve2dTool.hxx>
21 #include <Extrema_ECC2d.hxx>
22 #include <Extrema_ExtCC2d.hxx>
23 #include <Extrema_ExtElC.hxx>
24 #include <Extrema_ExtElC2d.hxx>
25 #include <Extrema_POnCurv2d.hxx>
26 #include <Extrema_SequenceOfPOnCurv2d.hxx>
27 #include <Geom2d_Circle.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <Geom2d_Ellipse.hxx>
30 #include <Geom2d_Hyperbola.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2d_Parabola.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <GeomAbs_CurveType.hxx>
35 #include <gp_Pnt2d.hxx>
36 #include <Precision.hxx>
37 #include <Standard_OutOfRange.hxx>
38 #include <StdFail_NotDone.hxx>
40 Extrema_ExtCC2d::Extrema_ExtCC2d()
41 : myIsFindSingleSolution(Standard_False)
46 Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1,
47 const Adaptor2d_Curve2d& C2,
48 const Standard_Real TolC1,
49 const Standard_Real TolC2)
50 : myIsFindSingleSolution(Standard_False)
52 Initialize(C2, Extrema_Curve2dTool::FirstParameter(C2), Extrema_Curve2dTool::LastParameter(C2), TolC1, TolC2);
53 Perform(C1, Extrema_Curve2dTool::FirstParameter(C1), Extrema_Curve2dTool::LastParameter(C1));
56 Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1,
57 const Adaptor2d_Curve2d& C2,
58 const Standard_Real U1,
59 const Standard_Real U2,
60 const Standard_Real V1,
61 const Standard_Real V2,
62 const Standard_Real TolC1,
63 const Standard_Real TolC2)
64 : myIsFindSingleSolution(Standard_False)
66 Initialize(C2, V1, V2, TolC1, TolC2);
72 void Extrema_ExtCC2d::Initialize(const Adaptor2d_Curve2d& C2,
73 const Standard_Real V1,
74 const Standard_Real V2,
75 const Standard_Real TolC1,
76 const Standard_Real TolC2)
78 myC = (Standard_Address)&C2;
87 void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1,
88 const Standard_Real U1,
89 const Standard_Real U2)
93 GeomAbs_CurveType type1 = Extrema_Curve2dTool::GetType(C1), type2 = Extrema_Curve2dTool::GetType(*((Adaptor2d_Curve2d*)myC));
94 Standard_Real U11, U12, U21, U22, Tol = Min(mytolc1, mytolc2);
95 // Extrema_POnCurv2d P1, P2;
97 inverse = Standard_False;
98 myIsPar = Standard_False;
104 P1f = Extrema_Curve2dTool::Value(C1, U11);
105 P1l = Extrema_Curve2dTool::Value(C1, U12);
106 P2f = Extrema_Curve2dTool::Value(*((Adaptor2d_Curve2d*)myC), U21);
107 P2l = Extrema_Curve2dTool::Value(*((Adaptor2d_Curve2d*)myC), U22);
112 // La premiere courbe est un cercle:
114 case GeomAbs_Circle: {
118 inverse = Standard_True;
119 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Circle(C1), Tol);
120 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
123 case GeomAbs_Circle: {
124 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(C1), Extrema_Curve2dTool::Circle(*((Adaptor2d_Curve2d*)myC)));
125 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI);
128 case GeomAbs_Ellipse: {
129 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)));
130 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI );
133 case GeomAbs_Parabola: {
134 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
135 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
138 case GeomAbs_Hyperbola: {
139 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
140 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0. );
144 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
145 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
146 aParamSolver.Perform();
147 Standard_Real Period2 = 0.;
148 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
149 Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
157 // La premiere courbe est une ellipse:
159 case GeomAbs_Ellipse: {
163 inverse = Standard_True;
164 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Ellipse(C1));
165 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
168 case GeomAbs_Circle: {
169 inverse = Standard_True;
170 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Ellipse(C1));
171 Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI);
174 case GeomAbs_Ellipse:
176 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
177 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
178 aParamSolver.Perform();
179 Results(aParamSolver, U11, U12, U21, U22,2*M_PI, 2*M_PI);
182 case GeomAbs_Parabola: {
183 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
184 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
185 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
186 aParamSolver.Perform();
187 Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
190 case GeomAbs_Hyperbola: {
191 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
192 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
193 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
194 aParamSolver.Perform();
195 Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
199 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
200 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
201 aParamSolver.Perform();
202 Standard_Real Period2 = 0.;
203 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
204 Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
212 // La premiere courbe est une parabole:
214 case GeomAbs_Parabola: {
218 inverse = Standard_True;
219 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
220 Results(Xtrem, U11, U12, U21, U22, 0., 0.);
223 case GeomAbs_Circle: {
224 inverse = Standard_True;
225 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
226 Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
229 case GeomAbs_Ellipse: {
230 //inverse = Standard_True;
231 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
232 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
233 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
234 aParamSolver.Perform();
235 Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI);
238 case GeomAbs_Parabola: {
239 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Parabola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
240 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
241 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
242 aParamSolver.Perform();
243 Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
246 case GeomAbs_Hyperbola: {
247 //inverse = Standard_True;
248 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
249 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
250 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
251 aParamSolver.Perform();
252 Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
256 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
257 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
258 aParamSolver.Perform();
259 Standard_Real Period2 = 0.;
260 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
261 Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
269 // La premiere courbe est une hyperbole:
271 case GeomAbs_Hyperbola: {
275 inverse = Standard_True;
276 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
277 Results(Xtrem, U11, U12, U21, U22, 0., 0.);
280 case GeomAbs_Circle: {
281 inverse = Standard_True;
282 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Circle(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
283 Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
286 case GeomAbs_Ellipse: {
287 //inverse = Standard_True;
288 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
289 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
290 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
291 aParamSolver.Perform();
292 Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI );
295 case GeomAbs_Parabola: {
296 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
297 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
298 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
299 aParamSolver.Perform();
300 Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
303 case GeomAbs_Hyperbola: {
304 //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
305 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
306 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
307 aParamSolver.Perform();
308 Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
312 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
313 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
314 aParamSolver.Perform();
315 Standard_Real Period2 = 0.;
316 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
317 Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
325 // La premiere courbe est une Line:
331 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(C1), Extrema_Curve2dTool::Line(*((Adaptor2d_Curve2d*)myC)), Tol);
332 Results(Xtrem, U11, U12, U21, U22, 0., 0.);
335 case GeomAbs_Circle: {
336 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(C1), Extrema_Curve2dTool::Circle(*((Adaptor2d_Curve2d*)myC)), Tol);
337 Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
340 case GeomAbs_Ellipse: {
341 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)));
342 Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
345 case GeomAbs_Parabola: {
346 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
347 Results(Xtrem, U11, U12, U21, U22, 0., 0.);
350 case GeomAbs_Hyperbola: {
351 Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Line(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
352 Results(Xtrem, U11, U12, U21, U22, 0., 0.);
356 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
357 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
358 aParamSolver.Perform();
359 Standard_Real Period2 = 0.;
360 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
361 Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
369 // La premiere courbe est une BezierCurve ou une BSplineCurve:
372 Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
373 aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
374 aParamSolver.Perform();
375 Standard_Real Period1 = 0.;
376 if (Extrema_Curve2dTool::IsPeriodic(C1)) Period1 = Extrema_Curve2dTool::Period(C1);
377 Standard_Real Period2 = 0.;
378 if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
379 Results(aParamSolver, U11, U12, U21, U22, Period1, Period2);
388 Standard_Boolean Extrema_ExtCC2d::IsDone() const
394 Standard_Real Extrema_ExtCC2d::SquareDistance(const Standard_Integer N) const
396 if(!myDone) throw StdFail_NotDone();
397 if ((N <= 0) || (N > mynbext)) throw Standard_OutOfRange();
398 return mySqDist.Value(N);
402 Standard_Integer Extrema_ExtCC2d::NbExt() const
404 if(!myDone) throw StdFail_NotDone();
409 void Extrema_ExtCC2d::Points(const Standard_Integer N,
410 Extrema_POnCurv2d& P1,
411 Extrema_POnCurv2d& P2) const
413 if(!myDone) throw StdFail_NotDone();
414 if ((N <= 0) || (N > mynbext)) throw Standard_OutOfRange();
415 P1 = mypoints.Value(2*N-1);
416 P2 = mypoints.Value(2*N);
421 void Extrema_ExtCC2d::TrimmedSquareDistances(Standard_Real& dist11,
422 Standard_Real& dist12,
423 Standard_Real& dist21,
424 Standard_Real& dist22,
442 void Extrema_ExtCC2d::Results(const Extrema_ExtElC2d& AlgExt,
443 const Standard_Real Ut11,
444 const Standard_Real Ut12,
445 const Standard_Real Ut21,
446 const Standard_Real Ut22,
447 const Standard_Real Period1,
448 const Standard_Real Period2)
450 Standard_Integer i, NbExt;
451 Standard_Real Val, U, U2;
452 Extrema_POnCurv2d P1, P2;
454 myDone = AlgExt.IsDone();
455 myIsPar = AlgExt.IsParallel();
458 NbExt = AlgExt.NbExt();
459 for (i = 1; i <= NbExt; i++) {
460 // Verification de la validite des parametres pour le cas trimme:
461 AlgExt.Points(i, P1, P2);
464 if (Period1 != 0.0) U = ElCLib::InPeriod(U,Ut11,Ut11+Period1);
466 if (Period2 != 0.0) U2 = ElCLib::InPeriod(U2,Ut21,Ut21+Period2);
470 if (Period2 != 0.0) U2 = ElCLib::InPeriod(U2,Ut21,Ut21+Period2);
472 if (Period1 != 0.0) U = ElCLib::InPeriod(U,Ut11,Ut11+Period1);
474 if ((U >= Ut11 - Precision::PConfusion()) &&
475 (U <= Ut12 + Precision::PConfusion()) &&
476 (U2 >= Ut21 - Precision::PConfusion()) &&
477 (U2 <= Ut22 + Precision::PConfusion())) {
479 Val = AlgExt.SquareDistance(i);
480 mySqDist.Append(Val);
482 P1.SetValues(U, P1.Value());
483 P2.SetValues(U2, P2.Value());
488 P1.SetValues(U2, P1.Value());
489 P2.SetValues(U, P2.Value());
497 mydist11 = P1f.SquareDistance(P2f);
498 mydist12 = P1f.SquareDistance(P2l);
499 mydist21 = P1l.SquareDistance(P2f);
500 mydist22 = P1l.SquareDistance(P2l);
505 void Extrema_ExtCC2d::Results(const Extrema_ECC2d& AlgExt,
506 const Standard_Real Ut11,
507 const Standard_Real Ut12,
508 const Standard_Real Ut21,
509 const Standard_Real Ut22,
510 const Standard_Real Period1,
511 const Standard_Real Period2)
513 Standard_Integer i, NbExt;
514 Standard_Real Val, U, U2;
515 Extrema_POnCurv2d P1, P2;
517 myDone = AlgExt.IsDone();
520 myIsPar = AlgExt.IsParallel();
521 NbExt = AlgExt.NbExt();
522 for (i = 1; i <= NbExt; i++)
524 // Verification de la validite des parametres pour le cas trimme:
525 AlgExt.Points(i, P1, P2);
528 U = ElCLib::InPeriod(U,Ut11,Ut11+Period1);
531 U2 = ElCLib::InPeriod(U2,Ut21,Ut21+Period2);
533 if ((U >= Ut11 - Precision::PConfusion()) &&
534 (U <= Ut12 + Precision::PConfusion()) &&
535 (U2 >= Ut21 - Precision::PConfusion()) &&
536 (U2 <= Ut22 + Precision::PConfusion()))
539 Val = AlgExt.SquareDistance(i);
540 P1.SetValues(U, P1.Value());
541 P2.SetValues(U2, P2.Value());
542 mySqDist.Append(Val);
548 mydist11 = P1f.SquareDistance(P2f);
549 mydist12 = P1f.SquareDistance(P2l);
550 mydist21 = P1l.SquareDistance(P2f);
551 mydist22 = P1l.SquareDistance(P2l);
556 Standard_Boolean Extrema_ExtCC2d::IsParallel() const
558 if (!myDone) throw StdFail_NotDone();
562 //=======================================================================
563 //function : SetSingleSolutionFlag
565 //=======================================================================
566 void Extrema_ExtCC2d::SetSingleSolutionFlag(const Standard_Boolean theFlag)
568 myIsFindSingleSolution = theFlag;
571 //=======================================================================
572 //function : GetSingleSolutionFlag
574 //=======================================================================
575 Standard_Boolean Extrema_ExtCC2d::GetSingleSolutionFlag() const
577 return myIsFindSingleSolution;