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