1 // Created on: 1994-01-04
2 // Created by: Christophe MARION
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
23 #include <Extrema_ExtElC2d.ixx>
25 #include <StdFail_InfiniteSolutions.hxx>
26 #include <StdFail_NotDone.hxx>
28 #include <math_TrigonometricFunctionRoots.hxx>
29 #include <math_DirectPolynomialRoots.hxx>
30 #include <Standard_OutOfRange.hxx>
31 #include <Standard_NotImplemented.hxx>
32 #include <Precision.hxx>
33 #include <Extrema_ExtPElC2d.hxx>
35 //=============================================================================
37 Extrema_ExtElC2d::Extrema_ExtElC2d () { myDone = Standard_False; }
38 //=============================================================================
40 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1,
43 /*-----------------------------------------------------------------------------
45 Find min distance between 2 straight lines.
48 Let D1 and D2 be 2 directions of straight lines C1 and C2.
49 2 cases are considered:
50 1- if Angle(D1,D2) < AngTol, the straight lines are parallel.
51 The distance is the distance between any point of C1 and straight line C2.
52 2- if Angle(D1,D2) > AngTol:
53 Let P = C1(u1) and P =C2(u2) the point intersection:
55 -----------------------------------------------------------------------------*/
57 myDone = Standard_False;
58 myIsPar = Standard_False;
61 gp_Dir2d D1 = C1.Direction();
62 gp_Dir2d D2 = C2.Direction();
63 if (D1.IsParallel(D2, Precision::Angular())) {
64 myIsPar = Standard_True;
65 mySqDist[0] = C2.SquareDistance(C1.Location());
70 myDone = Standard_True;
72 //=============================================================================
74 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1,
77 /*-----------------------------------------------------------------------------
79 Find extreme distances between straight line C1 and circle C2.
82 Let P1=C1(u1) and P2=C2(u2) be two solution points
83 D the direction of straight line C1
84 T the tangent at point P2;
85 Then, ( P1P2.D = 0. (1)
87 -----------------------------------------------------------------------------*/
89 myIsPar = Standard_False;
90 myDone = Standard_False;
93 // Calculate T1 in the reference of the circle ...
94 gp_Dir2d D = C1.Direction();
96 x2 = C2.XAxis().Direction();
97 y2 = C2.YAxis().Direction();
99 Standard_Real Dx = D.Dot(x2);
100 Standard_Real Dy = D.Dot(y2);
101 Standard_Real U1, teta[2];
102 gp_Pnt2d O1=C1.Location();
104 gp_Pnt2d O2= C2.Location();
111 if (Abs(Dy) <= RealEpsilon()) {
114 else teta[0] = ATan(-Dx/Dy);
115 teta[1] = teta[0]+ M_PI;
116 if (teta[0] < 0.0) teta[0] = teta[0] + 2.0*M_PI;
118 P2 = ElCLib::Value(teta[0], C2);
119 U1 = (gp_Vec2d(O1, P2)).Dot(D);
120 P1 = ElCLib::Value(U1, C1);
121 mySqDist[myNbExt] = P1.SquareDistance(P2);
122 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
123 myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
126 P2 = ElCLib::Value(teta[1], C2);
127 U1 = (gp_Vec2d(O1, P2)).Dot(D);
128 P1 = ElCLib::Value(U1, C1);
129 mySqDist[myNbExt] = P1.SquareDistance(P2);
130 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
131 myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
133 myDone = Standard_True;
137 // =============================================================================
138 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1,
139 const gp_Elips2d& C2)
141 myDone = Standard_True;
142 myIsPar = Standard_False;
143 myDone = Standard_False;
146 // Calculate T1 in the reference of the ellipse ...
147 gp_Dir2d D = C1.Direction();
149 x2 = C2.XAxis().Direction();
150 y2 = C2.YAxis().Direction();
152 Standard_Real Dx = D.Dot(x2);
153 Standard_Real Dy = D.Dot(y2);
154 Standard_Real U1, teta[2], r1 = C2.MajorRadius(), r2 = C2.MinorRadius();
156 gp_Pnt2d O1=C1.Location(), O2= C2.Location(), P1, P2;
158 gp_Pnt2d O1=C1.Location(), P1, P2;
161 if (Abs(Dy) <= RealEpsilon()) {
164 else teta[0] = ATan(-Dx*r2/(Dy*r1));
166 teta[1] = teta[0] + M_PI;
167 if (teta[0] < 0.0) teta[0] += 2.0*M_PI;
168 P2 = ElCLib::Value(teta[0], C2);
169 U1 = (gp_Vec2d(O1, P2)).Dot(D);
170 P1 = ElCLib::Value(U1, C1);
171 mySqDist[myNbExt] = P1.SquareDistance(P2);
172 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
173 myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
177 P2 = ElCLib::Value(teta[1], C2);
178 U1 = (gp_Vec2d(O1, P2)).Dot(D);
179 P1 = ElCLib::Value(U1, C1);
180 mySqDist[myNbExt] = P1.SquareDistance(P2);
181 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
182 myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
184 myDone = Standard_True;
189 //=============================================================================
191 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Hypr2d& C2)
193 myIsPar = Standard_False;
194 myDone = Standard_False;
197 // Calculate T1 in the reference of the parabole ...
198 gp_Dir2d D = C1.Direction();
200 x2 = C2.XAxis().Direction();
201 y2 = C2.YAxis().Direction();
202 Standard_Real Dx = D.Dot(x2);
203 Standard_Real Dy = D.Dot(y2);
205 Standard_Real U1, v2, U2=0, R = C2.MajorRadius(), r = C2.MinorRadius();
207 if (Abs(Dy) < RealEpsilon()) { return;}
208 if (Abs(R - r*Dx/Dy) < RealEpsilon()) return;
210 v2 = (R + r*Dx/Dy)/(R - r*Dx/Dy);
211 if (v2 > 0.0) U2 = Log(Sqrt(v2));
212 P2 = ElCLib::Value(U2, C2);
214 U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
215 P1 = ElCLib::Value(U1, C1);
216 mySqDist[myNbExt] = P1.SquareDistance(P2);
217 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
218 myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
220 myDone = Standard_True;
225 //============================================================================
227 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Parab2d& C2)
229 myIsPar = Standard_False;
230 myDone = Standard_False;
233 // Calculate T1 in the reference of the parabole ...
234 gp_Dir2d D = C1.Direction();
236 x2 = C2.MirrorAxis().Direction();
237 y2 = C2.Axis().YAxis().Direction();
238 Standard_Real Dx = D.Dot(x2);
239 Standard_Real Dy = D.Dot(y2);
241 Standard_Real U1, U2, P = C2.Parameter();
243 if (Abs(Dy) < RealEpsilon()) { return; }
245 P2 = ElCLib::Value(U2, C2);
247 U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
248 P1 = ElCLib::Value(U1, C1);
249 mySqDist[myNbExt] = P1.SquareDistance(P2);
250 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
251 myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
253 myDone = Standard_True;
258 //============================================================================
260 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Circ2d& C2)
262 myIsPar = Standard_False;
263 myDone = Standard_False;
265 myDone = Standard_True;
267 gp_Pnt2d O1 = C1.Location();
268 gp_Pnt2d O2 = C2.Location();
270 gp_Vec2d DO1O2 (O1, O2);
271 if (DO1O2.Magnitude() < Precision::Confusion()) {
272 myIsPar = Standard_True;
276 Standard_Integer NoSol, kk;
277 Standard_Real U1, U2;
278 Standard_Real r1 = C1.Radius(), r2 = C2.Radius();
279 Standard_Real Usol2[2], Usol1[2];
280 gp_Pnt2d P1[2], P2[2];
281 gp_Dir2d O1O2(DO1O2);
283 P1[0] = O1.Translated(r1*O1O2);
284 Usol1[0] = ElCLib::Parameter(C1, P1[0]);
285 P1[1] = O1.Translated(-r1*O1O2);
286 Usol1[1] = ElCLib::Parameter(C1, P1[1]);
288 P2[0] = O2.Translated(r2*O1O2);
289 Usol2[0] = ElCLib::Parameter(C2, P2[0]);
290 P2[1] = O2.Translated(-r2*O1O2);
291 Usol2[1] = ElCLib::Parameter(C2, P2[1]);
293 for (NoSol = 0; NoSol <= 1; NoSol++) {
295 for (kk = 0; kk <= 1; kk++) {
297 mySqDist[myNbExt] = P2[kk].SquareDistance(P1[NoSol]);
298 myPoint[myNbExt][0] = Extrema_POnCurv2d(U1, P1[NoSol]);
299 myPoint[myNbExt][1] = Extrema_POnCurv2d(U2, P2[kk]);
304 //===========================================================================
306 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Elips2d& C2)
308 myIsPar = Standard_False;
309 myDone = Standard_False;
312 Standard_Integer i, j;
314 Extrema_ExtPElC2d ExtElip(C1.Location(), C2,
315 Precision::Confusion(), 0.0, 2.0*M_PI);
317 if (ExtElip.IsDone()) {
318 for (i = 1; i <= ExtElip.NbExt(); i++) {
319 Extrema_ExtPElC2d ExtCirc(ExtElip.Point(i).Value(), C1,
320 Precision::Confusion(), 0.0, 2.0*M_PI);
321 if (ExtCirc.IsDone()) {
322 for (j = 1; j <= ExtCirc.NbExt(); j++) {
323 mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
324 myPoint[myNbExt][0] = ExtCirc.Point(j);
325 myPoint[myNbExt][1] = ExtElip.Point(i);
329 myDone = Standard_True;
333 //============================================================================
335 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Hypr2d& C2)
337 myIsPar = Standard_False;
338 myDone = Standard_False;
341 Standard_Integer i, j;
343 Extrema_ExtPElC2d ExtHyp(C1.Location(), C2, Precision::Confusion(),
344 RealFirst(), RealLast());
346 if (ExtHyp.IsDone()) {
347 for (i = 1; i <= ExtHyp.NbExt(); i++) {
348 Extrema_ExtPElC2d ExtCirc(ExtHyp.Point(i).Value(), C1,
349 Precision::Confusion(), 0.0, 2.0*M_PI);
350 if (ExtCirc.IsDone()) {
351 for (j = 1; j <= ExtCirc.NbExt(); j++) {
352 mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
353 myPoint[myNbExt][0] = ExtCirc.Point(j);
354 myPoint[myNbExt][1] = ExtHyp.Point(i);
358 myDone = Standard_True;
362 //============================================================================
364 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Parab2d& C2)
366 myIsPar = Standard_False;
367 myDone = Standard_False;
370 Standard_Integer i, j;
372 Extrema_ExtPElC2d ExtParab(C1.Location(), C2, Precision::Confusion(),
373 RealFirst(), RealLast());
375 if (ExtParab.IsDone()) {
376 for (i = 1; i <= ExtParab.NbExt(); i++) {
377 Extrema_ExtPElC2d ExtCirc(ExtParab.Point(i).Value(),
378 C1, Precision::Confusion(), 0.0, 2.0*M_PI);
379 if (ExtCirc.IsDone()) {
380 for (j = 1; j <= ExtCirc.NbExt(); j++) {
381 mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
382 myPoint[myNbExt][0] = ExtCirc.Point(j);
383 myPoint[myNbExt][1] = ExtParab.Point(i);
387 myDone = Standard_True;
391 //============================================================================
393 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Elips2d&)
395 Standard_NotImplemented::Raise();
397 //============================================================================
399 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Hypr2d&)
401 Standard_NotImplemented::Raise();
403 //============================================================================
405 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Parab2d&)
407 Standard_NotImplemented::Raise();
409 //============================================================================
411 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Hypr2d&)
413 Standard_NotImplemented::Raise();
415 //============================================================================
417 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Parab2d&)
419 Standard_NotImplemented::Raise();
421 //============================================================================
423 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Parab2d&, const gp_Parab2d&)
425 Standard_NotImplemented::Raise();
427 //============================================================================
429 Standard_Boolean Extrema_ExtElC2d::IsDone () const { return myDone; }
430 //============================================================================
432 Standard_Boolean Extrema_ExtElC2d::IsParallel () const
434 if (!IsDone()) { StdFail_NotDone::Raise(); }
437 //============================================================================
439 Standard_Integer Extrema_ExtElC2d::NbExt () const
441 if (IsParallel()) { StdFail_InfiniteSolutions::Raise(); }
444 //============================================================================
446 Standard_Real Extrema_ExtElC2d::SquareDistance (const Standard_Integer N) const
448 if (!(N == 1 && myDone)) {
449 if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
451 return mySqDist[N-1];
453 //============================================================================
455 void Extrema_ExtElC2d::Points (const Standard_Integer N,
456 Extrema_POnCurv2d& P1,
457 Extrema_POnCurv2d& P2) const
459 if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
460 P1 = myPoint[N-1][0];
461 P2 = myPoint[N-1][1];
463 //============================================================================