5a8f2a4b1fb74c40a75c066f0540a1da266d7e4b
[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 #ifdef DEB
98   gp_Pnt2d O2= C2.Location();
99   gp_Pnt2d P1, P2;
100 #else
101   C2.Location();
102   gp_Pnt2d P1, P2;
103 #endif
104   
105   if (Abs(Dy) <= RealEpsilon()) {
106     teta[0] = M_PI/2.0;
107   }
108   else  teta[0] = ATan(-Dx/Dy);
109   teta[1] = teta[0]+ M_PI;
110   if (teta[0] < 0.0) teta[0] = teta[0] + 2.0*M_PI;
111
112   P2 = ElCLib::Value(teta[0], C2);
113   U1 = (gp_Vec2d(O1, P2)).Dot(D);
114   P1 = ElCLib::Value(U1, C1);
115   mySqDist[myNbExt] = P1.SquareDistance(P2);
116   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
117   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
118   myNbExt++;
119
120   P2 = ElCLib::Value(teta[1], C2);
121   U1 = (gp_Vec2d(O1, P2)).Dot(D);
122   P1 = ElCLib::Value(U1, C1);
123   mySqDist[myNbExt] = P1.SquareDistance(P2);
124   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
125   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
126   myNbExt++;
127   myDone = Standard_True;
128 }
129
130
131 // =============================================================================
132 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
133                                     const gp_Elips2d& C2)
134 {
135   myDone = Standard_True;
136   myIsPar = Standard_False;
137   myDone = Standard_False;
138   myNbExt = 0;
139
140 // Calculate T1 in the reference of the ellipse ...
141   gp_Dir2d D = C1.Direction();
142   gp_Dir2d x2, y2;
143   x2 = C2.XAxis().Direction();
144   y2 = C2.YAxis().Direction();
145
146   Standard_Real Dx = D.Dot(x2);
147   Standard_Real Dy = D.Dot(y2);
148   Standard_Real U1, teta[2], r1 = C2.MajorRadius(), r2 = C2.MinorRadius();
149 #ifdef DEB
150   gp_Pnt2d O1=C1.Location(), O2= C2.Location(), P1, P2;
151 #else
152   gp_Pnt2d O1=C1.Location(), P1, P2;
153 #endif
154   
155   if (Abs(Dy) <= RealEpsilon()) {
156     teta[0] = M_PI/2.0;
157   }
158   else  teta[0] = ATan(-Dx*r2/(Dy*r1));
159
160   teta[1] = teta[0] + M_PI;
161   if (teta[0] < 0.0) teta[0] += 2.0*M_PI;
162   P2 = ElCLib::Value(teta[0], C2);
163   U1 = (gp_Vec2d(O1, P2)).Dot(D);
164   P1 = ElCLib::Value(U1, C1);
165   mySqDist[myNbExt] = P1.SquareDistance(P2);
166   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
167   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[0],P2);
168   myNbExt++;
169
170
171   P2 = ElCLib::Value(teta[1], C2);
172   U1 = (gp_Vec2d(O1, P2)).Dot(D);
173   P1 = ElCLib::Value(U1, C1);
174   mySqDist[myNbExt] = P1.SquareDistance(P2);
175   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
176   myPoint[myNbExt][1] = Extrema_POnCurv2d(teta[1],P2);
177   myNbExt++;
178   myDone = Standard_True;
179 }
180
181
182
183 //=============================================================================
184
185 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Hypr2d& C2)
186 {
187   myIsPar = Standard_False;
188   myDone = Standard_False;
189   myNbExt = 0;
190
191 // Calculate T1 in the reference of the parabole ...
192   gp_Dir2d D = C1.Direction();
193   gp_Dir2d x2, y2;
194   x2 = C2.XAxis().Direction();
195   y2 = C2.YAxis().Direction();
196   Standard_Real Dx = D.Dot(x2);
197   Standard_Real Dy = D.Dot(y2);
198
199   Standard_Real U1, v2, U2=0, R = C2.MajorRadius(), r = C2.MinorRadius();
200   gp_Pnt2d P1, P2;
201   if (Abs(Dy) < RealEpsilon()) { return;}
202   if (Abs(R - r*Dx/Dy) < RealEpsilon()) return;
203
204   v2 = (R + r*Dx/Dy)/(R - r*Dx/Dy);
205   if (v2 > 0.0) U2 = Log(Sqrt(v2));
206   P2 = ElCLib::Value(U2, C2);
207
208   U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
209   P1 = ElCLib::Value(U1, C1);
210   mySqDist[myNbExt] = P1.SquareDistance(P2);
211   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
212   myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
213   myNbExt++;
214   myDone = Standard_True;
215 }
216
217
218
219 //============================================================================
220
221 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Parab2d& C2)
222 {
223   myIsPar = Standard_False;
224   myDone = Standard_False;
225   myNbExt = 0;
226
227 // Calculate  T1 in the reference of the parabole ...
228   gp_Dir2d D = C1.Direction();
229   gp_Dir2d x2, y2;
230   x2 = C2.MirrorAxis().Direction();
231   y2 = C2.Axis().YAxis().Direction();
232   Standard_Real Dx = D.Dot(x2);
233   Standard_Real Dy = D.Dot(y2);
234
235   Standard_Real U1, U2, P = C2.Parameter();
236   gp_Pnt2d P1, P2;
237   if (Abs(Dy) < RealEpsilon()) { return; }
238   U2 = Dx*P/Dy;
239   P2 = ElCLib::Value(U2, C2);
240
241   U1 = (gp_Vec2d(C1.Location(), P2)).Dot(D);
242   P1 = ElCLib::Value(U1, C1);
243   mySqDist[myNbExt] = P1.SquareDistance(P2);
244   myPoint[myNbExt][0] = Extrema_POnCurv2d(U1,P1);
245   myPoint[myNbExt][1] = Extrema_POnCurv2d(U2,P2);
246   myNbExt++;
247   myDone = Standard_True;
248 }
249
250
251
252 //============================================================================
253
254 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Circ2d& C2)
255 {
256   myIsPar = Standard_False;
257   myDone  = Standard_False;
258   myNbExt = 0;
259   myDone  = Standard_True;
260
261   gp_Pnt2d O1 = C1.Location();
262   gp_Pnt2d O2 = C2.Location();
263
264   gp_Vec2d DO1O2 (O1, O2);
265   if (DO1O2.Magnitude() < Precision::Confusion()) { 
266     myIsPar = Standard_True;
267     return; 
268   }
269
270   Standard_Integer NoSol, kk;
271   Standard_Real U1, U2;
272   Standard_Real r1 = C1.Radius(), r2 = C2.Radius();
273   Standard_Real Usol2[2], Usol1[2];
274   gp_Pnt2d P1[2], P2[2];
275   gp_Dir2d O1O2(DO1O2);
276
277   P1[0] = O1.Translated(r1*O1O2);
278   Usol1[0] = ElCLib::Parameter(C1, P1[0]);
279   P1[1] = O1.Translated(-r1*O1O2);
280   Usol1[1] = ElCLib::Parameter(C1, P1[1]);
281   
282   P2[0] = O2.Translated(r2*O1O2);
283   Usol2[0] = ElCLib::Parameter(C2, P2[0]);
284   P2[1] = O2.Translated(-r2*O1O2);
285   Usol2[1] = ElCLib::Parameter(C2, P2[1]);
286   
287   for (NoSol = 0; NoSol <= 1; NoSol++) {
288     U1 = Usol1[NoSol];
289     for (kk = 0; kk <= 1; kk++) {
290       U2 = Usol2[kk];
291       mySqDist[myNbExt] = P2[kk].SquareDistance(P1[NoSol]);
292       myPoint[myNbExt][0] = Extrema_POnCurv2d(U1, P1[NoSol]);
293       myPoint[myNbExt][1] = Extrema_POnCurv2d(U2, P2[kk]);
294       myNbExt++;
295     }
296   }
297 }
298 //===========================================================================
299
300 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Elips2d& C2)
301 {
302   myIsPar = Standard_False;
303   myDone = Standard_False;
304   myNbExt = 0;
305
306   Standard_Integer i, j;
307
308   Extrema_ExtPElC2d ExtElip(C1.Location(), C2, 
309                             Precision::Confusion(), 0.0, 2.0*M_PI);
310   
311   if (ExtElip.IsDone()) {
312     for (i = 1; i <= ExtElip.NbExt(); i++) {
313       Extrema_ExtPElC2d ExtCirc(ExtElip.Point(i).Value(), C1, 
314                                 Precision::Confusion(), 0.0, 2.0*M_PI);
315       if (ExtCirc.IsDone()) {
316         for (j = 1; j <= ExtCirc.NbExt(); j++) {
317           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
318           myPoint[myNbExt][0] = ExtCirc.Point(j);
319           myPoint[myNbExt][1] = ExtElip.Point(i);
320           myNbExt++;
321         }
322       }
323       myDone = Standard_True;
324     }
325   }
326 }
327 //============================================================================
328
329 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Hypr2d& C2)
330 {
331   myIsPar = Standard_False;
332   myDone = Standard_False;
333   myNbExt = 0;
334
335   Standard_Integer i, j;
336
337   Extrema_ExtPElC2d ExtHyp(C1.Location(), C2, Precision::Confusion(), 
338                            RealFirst(), RealLast());
339   
340   if (ExtHyp.IsDone()) {
341     for (i = 1; i <= ExtHyp.NbExt(); i++) {
342       Extrema_ExtPElC2d ExtCirc(ExtHyp.Point(i).Value(), C1, 
343                                 Precision::Confusion(), 0.0, 2.0*M_PI);
344       if (ExtCirc.IsDone()) {
345         for (j = 1; j <= ExtCirc.NbExt(); j++) {
346           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
347           myPoint[myNbExt][0] = ExtCirc.Point(j);
348           myPoint[myNbExt][1] = ExtHyp.Point(i);
349           myNbExt++;
350         }
351       }
352       myDone = Standard_True;
353     }
354   }
355 }
356 //============================================================================
357
358 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Parab2d& C2)
359 {
360   myIsPar = Standard_False;
361   myDone = Standard_False;
362   myNbExt = 0;
363
364   Standard_Integer i, j;
365
366   Extrema_ExtPElC2d ExtParab(C1.Location(), C2, Precision::Confusion(),
367                              RealFirst(), RealLast());
368   
369   if (ExtParab.IsDone()) {
370     for (i = 1; i <= ExtParab.NbExt(); i++) {
371       Extrema_ExtPElC2d ExtCirc(ExtParab.Point(i).Value(), 
372                                 C1, Precision::Confusion(), 0.0, 2.0*M_PI);
373       if (ExtCirc.IsDone()) {
374         for (j = 1; j <= ExtCirc.NbExt(); j++) {
375           mySqDist[myNbExt] = ExtCirc.SquareDistance(j);
376           myPoint[myNbExt][0] = ExtCirc.Point(j);
377           myPoint[myNbExt][1] = ExtParab.Point(i);
378           myNbExt++;
379         }
380       }
381       myDone = Standard_True;
382     }
383   }
384 }
385 //============================================================================
386
387 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Elips2d&)
388 {
389   Standard_NotImplemented::Raise();
390 }
391 //============================================================================
392
393 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Hypr2d&)
394 {
395   Standard_NotImplemented::Raise();
396 }
397 //============================================================================
398
399 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Parab2d&)
400 {
401   Standard_NotImplemented::Raise();
402 }
403 //============================================================================
404
405 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Hypr2d&)
406 {
407   Standard_NotImplemented::Raise();
408 }
409 //============================================================================
410
411 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Parab2d&)
412 {
413   Standard_NotImplemented::Raise();
414 }
415 //============================================================================
416
417 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Parab2d&, const gp_Parab2d&)
418 {
419   Standard_NotImplemented::Raise();
420 }
421 //============================================================================
422
423 Standard_Boolean Extrema_ExtElC2d::IsDone () const { return myDone; }
424 //============================================================================
425
426 Standard_Boolean Extrema_ExtElC2d::IsParallel () const
427 {
428   if (!IsDone()) { StdFail_NotDone::Raise(); }
429   return myIsPar;
430 }
431 //============================================================================
432
433 Standard_Integer Extrema_ExtElC2d::NbExt () const
434 {
435   if (IsParallel()) { StdFail_InfiniteSolutions::Raise(); }
436   return myNbExt;
437 }
438 //============================================================================
439
440 Standard_Real Extrema_ExtElC2d::SquareDistance (const Standard_Integer N) const
441 {
442   if (!(N == 1 && myDone)) {
443     if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
444   }
445   return mySqDist[N-1];
446 }
447 //============================================================================
448
449 void Extrema_ExtElC2d::Points (const Standard_Integer N,
450                                Extrema_POnCurv2d& P1, 
451                                Extrema_POnCurv2d& P2) const
452 {
453   if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
454   P1 = myPoint[N-1][0];
455   P2 = myPoint[N-1][1];
456 }
457 //============================================================================