f26b2b8ac7caa490aa7aefecf4c7ce1ecefa02dd
[occt.git] / src / Extrema / Extrema_ExtElC2d.cxx
1 // Created on: 1994-01-04
2 // Created by: Christophe MARION
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public 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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Extrema_ExtElC2d.ixx>
18
19 #include <StdFail_InfiniteSolutions.hxx>
20 #include <StdFail_NotDone.hxx>
21 #include <ElCLib.hxx>
22 #include <math_TrigonometricFunctionRoots.hxx>
23 #include <math_DirectPolynomialRoots.hxx>
24 #include <Standard_OutOfRange.hxx>
25 #include <Standard_NotImplemented.hxx>
26 #include <Precision.hxx>
27 #include <Extrema_ExtPElC2d.hxx>
28
29 //=============================================================================
30
31 Extrema_ExtElC2d::Extrema_ExtElC2d () { myDone = Standard_False; }
32 //=============================================================================
33
34 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
35                                     const gp_Lin2d& C2,
36                                     const Standard_Real)
37 /*-----------------------------------------------------------------------------
38 Function:
39    Find min distance between 2 straight lines.
40
41 Method:
42   Let D1 and D2 be 2 directions of straight lines C1 and C2.
43   2 cases are considered:
44   1- if Angle(D1,D2) < AngTol, the straight lines are parallel.
45      The distance is the distance between any point of C1 and straight line C2.
46   2- if Angle(D1,D2) > AngTol:
47      Let P = C1(u1) and P =C2(u2) the point intersection:
48      
49 -----------------------------------------------------------------------------*/
50 {
51   myDone = Standard_False;
52   myIsPar = Standard_False;
53   myNbExt = 0;
54
55   gp_Dir2d D1 = C1.Direction();
56   gp_Dir2d D2 = C2.Direction();
57   if (D1.IsParallel(D2, Precision::Angular())) {
58     myIsPar = Standard_True;
59     mySqDist[0] = C2.SquareDistance(C1.Location());
60   }
61   else {
62     myNbExt = 0;
63   }
64   myDone = Standard_True;
65 }
66 //=============================================================================
67
68 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
69                                     const gp_Circ2d& C2,
70                                     const Standard_Real)
71 /*-----------------------------------------------------------------------------
72 Function:
73   Find extreme distances between straight line C1 and circle C2.
74
75 Method:
76   Let P1=C1(u1) and P2=C2(u2) be two solution points
77         D the direction of straight line C1
78         T the tangent at point P2;
79   Then, ( P1P2.D = 0. (1)
80          ( P1P2.T = 0. (2)
81 -----------------------------------------------------------------------------*/
82 {
83   myIsPar = Standard_False;
84   myDone = Standard_False;
85   myNbExt = 0;
86
87 // Calculate T1 in the reference of the circle ...
88   gp_Dir2d D = C1.Direction();
89   gp_Dir2d x2, y2;
90   x2 = C2.XAxis().Direction();
91   y2 = C2.YAxis().Direction();
92
93   Standard_Real Dx = D.Dot(x2);
94   Standard_Real Dy = D.Dot(y2);
95   Standard_Real U1, teta[2];
96   gp_Pnt2d O1=C1.Location();
97   gp_Pnt2d P1, P2;
98   
99   if (Abs(Dy) <= RealEpsilon()) {
100     teta[0] = M_PI/2.0;
101   }
102   else  teta[0] = ATan(-Dx/Dy);
103   teta[1] = teta[0]+ M_PI;
104   if (teta[0] < 0.0) teta[0] = teta[0] + 2.0*M_PI;
105
106   P2 = ElCLib::Value(teta[0], C2);
107   U1 = (gp_Vec2d(O1, P2)).Dot(D);
108   P1 = ElCLib::Value(U1, C1);
109   mySqDist[myNbExt] = P1.SquareDistance(P2);
110   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
111   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
112   myNbExt++;
113
114   P2 = ElCLib::Value(teta[1], C2);
115   U1 = (gp_Vec2d(O1, P2)).Dot(D);
116   P1 = ElCLib::Value(U1, C1);
117   mySqDist[myNbExt] = P1.SquareDistance(P2);
118   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
119   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
120   myNbExt++;
121   myDone = Standard_True;
122 }
123
124
125 // =============================================================================
126 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
127                                     const gp_Elips2d& C2)
128 {
129   myDone = Standard_True;
130   myIsPar = Standard_False;
131   myDone = Standard_False;
132   myNbExt = 0;
133
134 // Calculate T1 in the reference of the ellipse ...
135   gp_Dir2d D = C1.Direction();
136   gp_Dir2d x2, y2;
137   x2 = C2.XAxis().Direction();
138   y2 = C2.YAxis().Direction();
139
140   Standard_Real Dx = D.Dot(x2);
141   Standard_Real Dy = D.Dot(y2);
142   Standard_Real U1, teta[2], r1 = C2.MajorRadius(), r2 = C2.MinorRadius();
143   gp_Pnt2d O1=C1.Location(), P1, P2;
144   
145   if (Abs(Dy) <= RealEpsilon()) {
146     teta[0] = M_PI/2.0;
147   }
148   else  teta[0] = ATan(-Dx*r2/(Dy*r1));
149
150   teta[1] = teta[0] + M_PI;
151   if (teta[0] < 0.0) teta[0] += 2.0*M_PI;
152   P2 = ElCLib::Value(teta[0], C2);
153   U1 = (gp_Vec2d(O1, P2)).Dot(D);
154   P1 = ElCLib::Value(U1, C1);
155   mySqDist[myNbExt] = P1.SquareDistance(P2);
156   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
157   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
158   myNbExt++;
159
160
161   P2 = ElCLib::Value(teta[1], C2);
162   U1 = (gp_Vec2d(O1, P2)).Dot(D);
163   P1 = ElCLib::Value(U1, C1);
164   mySqDist[myNbExt] = P1.SquareDistance(P2);
165   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
166   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
167   myNbExt++;
168   myDone = Standard_True;
169 }
170
171
172
173 //=============================================================================
174
175 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Hypr2d& C2)
176 {
177   myIsPar = Standard_False;
178   myDone = Standard_False;
179   myNbExt = 0;
180
181 // Calculate T1 in the reference of the parabole ...
182   gp_Dir2d D = C1.Direction();
183   gp_Dir2d x2, y2;
184   x2 = C2.XAxis().Direction();
185   y2 = C2.YAxis().Direction();
186   Standard_Real Dx = D.Dot(x2);
187   Standard_Real Dy = D.Dot(y2);
188
189   Standard_Real U1, v2, U2=0, R = C2.MajorRadius(), r = C2.MinorRadius();
190   gp_Pnt2d P1, P2;
191   if (Abs(Dy) < RealEpsilon()) { return;}
192   if (Abs(R - r*Dx/Dy) < RealEpsilon()) return;
193
194   v2 = (R + r*Dx/Dy)/(R - r*Dx/Dy);
195   if (v2 > 0.0) U2 = Log(Sqrt(v2));
196   P2 = ElCLib::Value(U2, C2);
197
198   U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
199   P1 = ElCLib::Value(U1, C1);
200   mySqDist[myNbExt] = P1.SquareDistance(P2);
201   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
202   myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
203   myNbExt++;
204   myDone = Standard_True;
205 }
206
207
208
209 //============================================================================
210
211 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Parab2d& C2)
212 {
213   myIsPar = Standard_False;
214   myDone = Standard_False;
215   myNbExt = 0;
216
217 // Calculate  T1 in the reference of the parabole ...
218   gp_Dir2d D = C1.Direction();
219   gp_Dir2d x2, y2;
220   x2 = C2.MirrorAxis().Direction();
221   y2 = C2.Axis().YAxis().Direction();
222   Standard_Real Dx = D.Dot(x2);
223   Standard_Real Dy = D.Dot(y2);
224
225   Standard_Real U1, U2, P = C2.Parameter();
226   gp_Pnt2d P1, P2;
227   if (Abs(Dy) < RealEpsilon()) { return; }
228   U2 = Dx*P/Dy;
229   P2 = ElCLib::Value(U2, C2);
230
231   U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
232   P1 = ElCLib::Value(U1, C1);
233   mySqDist[myNbExt] = P1.SquareDistance(P2);
234   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
235   myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
236   myNbExt++;
237   myDone = Standard_True;
238 }
239
240
241
242 //============================================================================
243
244 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Circ2d& C2)
245 {
246   myIsPar = Standard_False;
247   myDone  = Standard_False;
248   myNbExt = 0;
249   myDone  = Standard_True;
250
251   gp_Pnt2d O1 = C1.Location();
252   gp_Pnt2d O2 = C2.Location();
253
254   gp_Vec2d DO1O2 (O1, O2);
255   if (DO1O2.Magnitude() < Precision::Confusion()) { 
256     myIsPar = Standard_True;
257     return; 
258   }
259
260   Standard_Integer NoSol, kk;
261   Standard_Real U1, U2;
262   Standard_Real r1 = C1.Radius(), r2 = C2.Radius();
263   Standard_Real Usol2[2], Usol1[2];
264   gp_Pnt2d P1[2], P2[2];
265   gp_Dir2d O1O2(DO1O2);
266
267   P1[0] = O1.Translated(r1*O1O2);
268   Usol1[0] = ElCLib::Parameter(C1, P1[0]);
269   P1[1] = O1.Translated(-r1*O1O2);
270   Usol1[1] = ElCLib::Parameter(C1, P1[1]);
271   
272   P2[0] = O2.Translated(r2*O1O2);
273   Usol2[0] = ElCLib::Parameter(C2, P2[0]);
274   P2[1] = O2.Translated(-r2*O1O2);
275   Usol2[1] = ElCLib::Parameter(C2, P2[1]);
276   
277   for (NoSol = 0; NoSol <= 1; NoSol++) {
278     U1 = Usol1[NoSol];
279     for (kk = 0; kk <= 1; kk++) {
280       U2 = Usol2[kk];
281       mySqDist[myNbExt] = P2[kk].SquareDistance(P1[NoSol]);
282       myPoint[myNbExt][0] = Extrema_POnCurv2d(U1, P1[NoSol]);
283       myPoint[myNbExt][1] = Extrema_POnCurv2d(U2, P2[kk]);
284       myNbExt++;
285     }
286   }
287 }
288 //===========================================================================
289
290 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Elips2d& C2)
291 {
292   myIsPar = Standard_False;
293   myDone = Standard_False;
294   myNbExt = 0;
295
296   Standard_Integer i, j;
297
298   Extrema_ExtPElC2d ExtElip(C1.Location(), C2, 
299                             Precision::Confusion(), 0.0, 2.0*M_PI);
300   
301   if (ExtElip.IsDone()) {
302     for (i = 1; i <= ExtElip.NbExt(); i++) {
303       Extrema_ExtPElC2d ExtCirc(ExtElip.Point(i).Value(), C1, 
304                                 Precision::Confusion(), 0.0, 2.0*M_PI);
305       if (ExtCirc.IsDone()) {
306         for (j = 1; j <= ExtCirc.NbExt(); j++) {
307           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
308           myPoint[myNbExt][0] = ExtCirc.Point(j);
309           myPoint[myNbExt][1] = ExtElip.Point(i);
310           myNbExt++;
311         }
312       }
313       myDone = Standard_True;
314     }
315   }
316 }
317 //============================================================================
318
319 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Hypr2d& C2)
320 {
321   myIsPar = Standard_False;
322   myDone = Standard_False;
323   myNbExt = 0;
324
325   Standard_Integer i, j;
326
327   Extrema_ExtPElC2d ExtHyp(C1.Location(), C2, Precision::Confusion(), 
328                            RealFirst(), RealLast());
329   
330   if (ExtHyp.IsDone()) {
331     for (i = 1; i <= ExtHyp.NbExt(); i++) {
332       Extrema_ExtPElC2d ExtCirc(ExtHyp.Point(i).Value(), C1, 
333                                 Precision::Confusion(), 0.0, 2.0*M_PI);
334       if (ExtCirc.IsDone()) {
335         for (j = 1; j <= ExtCirc.NbExt(); j++) {
336           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
337           myPoint[myNbExt][0] = ExtCirc.Point(j);
338           myPoint[myNbExt][1] = ExtHyp.Point(i);
339           myNbExt++;
340         }
341       }
342       myDone = Standard_True;
343     }
344   }
345 }
346 //============================================================================
347
348 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Parab2d& C2)
349 {
350   myIsPar = Standard_False;
351   myDone = Standard_False;
352   myNbExt = 0;
353
354   Standard_Integer i, j;
355
356   Extrema_ExtPElC2d ExtParab(C1.Location(), C2, Precision::Confusion(),
357                              RealFirst(), RealLast());
358   
359   if (ExtParab.IsDone()) {
360     for (i = 1; i <= ExtParab.NbExt(); i++) {
361       Extrema_ExtPElC2d ExtCirc(ExtParab.Point(i).Value(), 
362                                 C1, Precision::Confusion(), 0.0, 2.0*M_PI);
363       if (ExtCirc.IsDone()) {
364         for (j = 1; j <= ExtCirc.NbExt(); j++) {
365           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
366           myPoint[myNbExt][0] = ExtCirc.Point(j);
367           myPoint[myNbExt][1] = ExtParab.Point(i);
368           myNbExt++;
369         }
370       }
371       myDone = Standard_True;
372     }
373   }
374 }
375 //============================================================================
376
377 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Elips2d&)
378 {
379   Standard_NotImplemented::Raise();
380 }
381 //============================================================================
382
383 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Hypr2d&)
384 {
385   Standard_NotImplemented::Raise();
386 }
387 //============================================================================
388
389 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Parab2d&)
390 {
391   Standard_NotImplemented::Raise();
392 }
393 //============================================================================
394
395 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Hypr2d&)
396 {
397   Standard_NotImplemented::Raise();
398 }
399 //============================================================================
400
401 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Parab2d&)
402 {
403   Standard_NotImplemented::Raise();
404 }
405 //============================================================================
406
407 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Parab2d&, const gp_Parab2d&)
408 {
409   Standard_NotImplemented::Raise();
410 }
411 //============================================================================
412
413 Standard_Boolean Extrema_ExtElC2d::IsDone () const { return myDone; }
414 //============================================================================
415
416 Standard_Boolean Extrema_ExtElC2d::IsParallel () const
417 {
418   if (!IsDone()) { StdFail_NotDone::Raise(); }
419   return myIsPar;
420 }
421 //============================================================================
422
423 Standard_Integer Extrema_ExtElC2d::NbExt () const
424 {
425   if (IsParallel()) { StdFail_InfiniteSolutions::Raise(); }
426   return myNbExt;
427 }
428 //============================================================================
429
430 Standard_Real Extrema_ExtElC2d::SquareDistance (const Standard_Integer N) const
431 {
432   if (!(N == 1 && myDone)) {
433     if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
434   }
435   return mySqDist[N-1];
436 }
437 //============================================================================
438
439 void Extrema_ExtElC2d::Points (const Standard_Integer N,
440                                Extrema_POnCurv2d& P1, 
441                                Extrema_POnCurv2d& P2) const
442 {
443   if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
444   P1 = myPoint[N-1][0];
445   P2 = myPoint[N-1][1];
446 }
447 //============================================================================