0023043: Wrong results of BRepExtrema_DistShapeShape: non-null minimum distance betwe...
[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-2012 OPEN CASCADE SAS
5 //
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.
10 //
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.
13 //
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.
20
21
22
23 #include <Extrema_ExtElC2d.ixx>
24
25 #include <StdFail_InfiniteSolutions.hxx>
26 #include <StdFail_NotDone.hxx>
27 #include <ElCLib.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>
34
35 //=============================================================================
36
37 Extrema_ExtElC2d::Extrema_ExtElC2d () { myDone = Standard_False; }
38 //=============================================================================
39
40 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
41                                     const gp_Lin2d& C2,
42                                     const Standard_Real)
43 /*-----------------------------------------------------------------------------
44 Function:
45    Find min distance between 2 straight lines.
46
47 Method:
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:
54      
55 -----------------------------------------------------------------------------*/
56 {
57   myDone = Standard_False;
58   myIsPar = Standard_False;
59   myNbExt = 0;
60
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());
66   }
67   else {
68     myNbExt = 0;
69   }
70   myDone = Standard_True;
71 }
72 //=============================================================================
73
74 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
75                                     const gp_Circ2d& C2,
76                                     const Standard_Real)
77 /*-----------------------------------------------------------------------------
78 Function:
79   Find extreme distances between straight line C1 and circle C2.
80
81 Method:
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)
86          ( P1P2.T = 0. (2)
87 -----------------------------------------------------------------------------*/
88 {
89   myIsPar = Standard_False;
90   myDone = Standard_False;
91   myNbExt = 0;
92
93 // Calculate T1 in the reference of the circle ...
94   gp_Dir2d D = C1.Direction();
95   gp_Dir2d x2, y2;
96   x2 = C2.XAxis().Direction();
97   y2 = C2.YAxis().Direction();
98
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();
103 #ifdef DEB
104   gp_Pnt2d O2= C2.Location();
105   gp_Pnt2d P1, P2;
106 #else
107   C2.Location();
108   gp_Pnt2d P1, P2;
109 #endif
110   
111   if (Abs(Dy) <= RealEpsilon()) {
112     teta[0] = M_PI/2.0;
113   }
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;
117
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);
124   myNbExt++;
125
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);
132   myNbExt++;
133   myDone = Standard_True;
134 }
135
136
137 // =============================================================================
138 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, 
139                                     const gp_Elips2d& C2)
140 {
141   myDone = Standard_True;
142   myIsPar = Standard_False;
143   myDone = Standard_False;
144   myNbExt = 0;
145
146 // Calculate T1 in the reference of the ellipse ...
147   gp_Dir2d D = C1.Direction();
148   gp_Dir2d x2, y2;
149   x2 = C2.XAxis().Direction();
150   y2 = C2.YAxis().Direction();
151
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();
155 #ifdef DEB
156   gp_Pnt2d O1=C1.Location(), O2= C2.Location(), P1, P2;
157 #else
158   gp_Pnt2d O1=C1.Location(), P1, P2;
159 #endif
160   
161   if (Abs(Dy) <= RealEpsilon()) {
162     teta[0] = M_PI/2.0;
163   }
164   else  teta[0] = ATan(-Dx*r2/(Dy*r1));
165
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);
174   myNbExt++;
175
176
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);
183   myNbExt++;
184   myDone = Standard_True;
185 }
186
187
188
189 //=============================================================================
190
191 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Hypr2d& C2)
192 {
193   myIsPar = Standard_False;
194   myDone = Standard_False;
195   myNbExt = 0;
196
197 // Calculate T1 in the reference of the parabole ...
198   gp_Dir2d D = C1.Direction();
199   gp_Dir2d x2, y2;
200   x2 = C2.XAxis().Direction();
201   y2 = C2.YAxis().Direction();
202   Standard_Real Dx = D.Dot(x2);
203   Standard_Real Dy = D.Dot(y2);
204
205   Standard_Real U1, v2, U2=0, R = C2.MajorRadius(), r = C2.MinorRadius();
206   gp_Pnt2d P1, P2;
207   if (Abs(Dy) < RealEpsilon()) { return;}
208   if (Abs(R - r*Dx/Dy) < RealEpsilon()) return;
209
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);
213
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);
219   myNbExt++;
220   myDone = Standard_True;
221 }
222
223
224
225 //============================================================================
226
227 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Lin2d& C1, const gp_Parab2d& C2)
228 {
229   myIsPar = Standard_False;
230   myDone = Standard_False;
231   myNbExt = 0;
232
233 // Calculate  T1 in the reference of the parabole ...
234   gp_Dir2d D = C1.Direction();
235   gp_Dir2d x2, y2;
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);
240
241   Standard_Real U1, U2, P = C2.Parameter();
242   gp_Pnt2d P1, P2;
243   if (Abs(Dy) < RealEpsilon()) { return; }
244   U2 = Dx*P/Dy;
245   P2 = ElCLib::Value(U2, C2);
246
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);
252   myNbExt++;
253   myDone = Standard_True;
254 }
255
256
257
258 //============================================================================
259
260 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Circ2d& C2)
261 {
262   myIsPar = Standard_False;
263   myDone  = Standard_False;
264   myNbExt = 0;
265   myDone  = Standard_True;
266
267   gp_Pnt2d O1 = C1.Location();
268   gp_Pnt2d O2 = C2.Location();
269
270   gp_Vec2d DO1O2 (O1, O2);
271   if (DO1O2.Magnitude() < Precision::Confusion()) { 
272     myIsPar = Standard_True;
273     return; 
274   }
275
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);
282
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]);
287   
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]);
292   
293   for (NoSol = 0; NoSol <= 1; NoSol++) {
294     U1 = Usol1[NoSol];
295     for (kk = 0; kk <= 1; kk++) {
296       U2 = Usol2[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]);
300       myNbExt++;
301     }
302   }
303 }
304 //===========================================================================
305
306 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Elips2d& C2)
307 {
308   myIsPar = Standard_False;
309   myDone = Standard_False;
310   myNbExt = 0;
311
312   Standard_Integer i, j;
313
314   Extrema_ExtPElC2d ExtElip(C1.Location(), C2, 
315                             Precision::Confusion(), 0.0, 2.0*M_PI);
316   
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);
326           myNbExt++;
327         }
328       }
329       myDone = Standard_True;
330     }
331   }
332 }
333 //============================================================================
334
335 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Hypr2d& C2)
336 {
337   myIsPar = Standard_False;
338   myDone = Standard_False;
339   myNbExt = 0;
340
341   Standard_Integer i, j;
342
343   Extrema_ExtPElC2d ExtHyp(C1.Location(), C2, Precision::Confusion(), 
344                            RealFirst(), RealLast());
345   
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);
355           myNbExt++;
356         }
357       }
358       myDone = Standard_True;
359     }
360   }
361 }
362 //============================================================================
363
364 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Circ2d& C1, const gp_Parab2d& C2)
365 {
366   myIsPar = Standard_False;
367   myDone = Standard_False;
368   myNbExt = 0;
369
370   Standard_Integer i, j;
371
372   Extrema_ExtPElC2d ExtParab(C1.Location(), C2, Precision::Confusion(),
373                              RealFirst(), RealLast());
374   
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);
384           myNbExt++;
385         }
386       }
387       myDone = Standard_True;
388     }
389   }
390 }
391 //============================================================================
392
393 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Elips2d&)
394 {
395   Standard_NotImplemented::Raise();
396 }
397 //============================================================================
398
399 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Hypr2d&)
400 {
401   Standard_NotImplemented::Raise();
402 }
403 //============================================================================
404
405 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Elips2d&, const gp_Parab2d&)
406 {
407   Standard_NotImplemented::Raise();
408 }
409 //============================================================================
410
411 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Hypr2d&)
412 {
413   Standard_NotImplemented::Raise();
414 }
415 //============================================================================
416
417 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Hypr2d&, const gp_Parab2d&)
418 {
419   Standard_NotImplemented::Raise();
420 }
421 //============================================================================
422
423 Extrema_ExtElC2d::Extrema_ExtElC2d (const gp_Parab2d&, const gp_Parab2d&)
424 {
425   Standard_NotImplemented::Raise();
426 }
427 //============================================================================
428
429 Standard_Boolean Extrema_ExtElC2d::IsDone () const { return myDone; }
430 //============================================================================
431
432 Standard_Boolean Extrema_ExtElC2d::IsParallel () const
433 {
434   if (!IsDone()) { StdFail_NotDone::Raise(); }
435   return myIsPar;
436 }
437 //============================================================================
438
439 Standard_Integer Extrema_ExtElC2d::NbExt () const
440 {
441   if (IsParallel()) { StdFail_InfiniteSolutions::Raise(); }
442   return myNbExt;
443 }
444 //============================================================================
445
446 Standard_Real Extrema_ExtElC2d::SquareDistance (const Standard_Integer N) const
447 {
448   if (!(N == 1 && myDone)) {
449     if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
450   }
451   return mySqDist[N-1];
452 }
453 //============================================================================
454
455 void Extrema_ExtElC2d::Points (const Standard_Integer N,
456                                Extrema_POnCurv2d& P1, 
457                                Extrema_POnCurv2d& P2) const
458 {
459   if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
460   P1 = myPoint[N-1][0];
461   P2 = myPoint[N-1][1];
462 }
463 //============================================================================