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