0030850: Visualization, OpenGl_Text - text within trihedron persistence jitters when...
[occt.git] / src / Extrema / Extrema_ExtElCS.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
15// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134
16
42cf5bc1 17#include <ElCLib.hxx>
18#include <ElSLib.hxx>
7fd59977 19#include <Extrema_ExtElC.hxx>
42cf5bc1 20#include <Extrema_ExtElCS.hxx>
21#include <Extrema_ExtPElC.hxx>
22#include <Extrema_ExtPElS.hxx>
7fd59977 23#include <Extrema_POnCurv.hxx>
42cf5bc1 24#include <Extrema_POnSurf.hxx>
25#include <gp_Circ.hxx>
26#include <gp_Cone.hxx>
27#include <gp_Cylinder.hxx>
28#include <gp_Hypr.hxx>
29#include <gp_Lin.hxx>
30#include <gp_Pln.hxx>
31#include <gp_Sphere.hxx>
32#include <gp_Torus.hxx>
7fd59977 33#include <gp_Vec.hxx>
f34cd0d1 34#include <IntAna_IntConicQuad.hxx>
42cf5bc1 35#include <IntAna_Quadric.hxx>
03cca6f7 36#include <IntAna_QuadQuadGeo.hxx>
42cf5bc1 37#include <Precision.hxx>
38#include <Standard_NotImplemented.hxx>
39#include <Standard_OutOfRange.hxx>
40#include <StdFail_InfiniteSolutions.hxx>
41#include <StdFail_NotDone.hxx>
03cca6f7 42#include <TColStd_ListOfInteger.hxx>
7fd59977 43
44Extrema_ExtElCS::Extrema_ExtElCS()
45{
46 myDone = Standard_False;
47 myIsPar = Standard_False;
638ad7f3 48 myNbExt = 0;
7fd59977 49}
50
51
52Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
53 const gp_Pln& S)
54{
55 Perform(C, S);
56}
57
58
59
60void Extrema_ExtElCS::Perform(const gp_Lin& C,
61 const gp_Pln& S)
62{
63 myDone = Standard_True;
64 myIsPar = Standard_False;
638ad7f3 65 myNbExt = 0;
7fd59977 66
638ad7f3 67 if (C.Direction().IsNormal(S.Axis().Direction(),
68 Precision::Angular()))
69 {
7fd59977 70 mySqDist = new TColStd_HArray1OfReal(1, 1);
71 mySqDist->SetValue(1, S.SquareDistance(C));
72 myIsPar = Standard_True;
638ad7f3 73 myNbExt = 1;
7fd59977 74 }
7fd59977 75}
76
77
78Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
79 const gp_Cylinder& S)
80{
81 Perform(C, S);
82}
83
84
85
86void Extrema_ExtElCS::Perform(const gp_Lin& C,
db914841 87 const gp_Cylinder& S)
7fd59977 88{
89 myDone = Standard_False;
90 myNbExt = 0;
91 myIsPar = Standard_False;
92
93 gp_Ax3 Pos = S.Position();
638ad7f3 94
95 Standard_Boolean isParallel = Standard_False;
f34cd0d1 96
7fd59977 97 Standard_Real radius = S.Radius();
98 Extrema_ExtElC Extrem(gp_Lin(Pos.Axis()), C, Precision::Angular());
638ad7f3 99 if (Extrem.IsParallel())
100 {
101 isParallel = Standard_True;
7fd59977 102 }
638ad7f3 103 else
104 {
db914841 105 Standard_Integer i, aStartIdx = 0;
106
f34cd0d1 107 Extrema_POnCurv myPOnC1, myPOnC2;
108 Extrem.Points(1, myPOnC1, myPOnC2);
109 gp_Pnt PonAxis = myPOnC1.Value();
110 gp_Pnt PC = myPOnC2.Value();
111
f34cd0d1 112 // line intersects the cylinder
db914841 113 if (radius - PonAxis.Distance(PC) > Precision::PConfusion())
f34cd0d1 114 {
115 IntAna_Quadric theQuadric(S);
116 IntAna_IntConicQuad Inters(C, theQuadric);
638ad7f3 117 if (Inters.IsDone() && Inters.IsInQuadric())
118 {
119 isParallel = Standard_True;
120 }
121 else if (Inters.IsDone())
f34cd0d1 122 {
123 myNbExt = Inters.NbPoints();
db914841 124 aStartIdx = myNbExt;
f34cd0d1 125 if (myNbExt > 0)
126 {
db914841 127 // Not more than 2 additional points from perpendiculars.
128 mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2);
129 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2);
130 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2);
f34cd0d1 131 Standard_Real u, v, w;
132 for (i = 1; i <= myNbExt; i++)
133 {
134 mySqDist->SetValue(i, 0.);
135 gp_Pnt P_int = Inters.Point(i);
136 w = Inters.ParamOnConic(i);
137 Extrema_POnCurv PonC(w, P_int);
138 myPoint1->SetValue(i, PonC);
139 ElSLib::CylinderParameters(Pos, radius, P_int, u, v);
140 Extrema_POnSurf PonS(u, v, P_int);
141 myPoint2->SetValue(i, PonS);
142 }
143 }
7fd59977 144 }
7fd59977 145 }
638ad7f3 146 else
147 {
148 // line is tangent or outside of the cylinder
149 Extrema_ExtPElS ExPS(PC, S, Precision::Confusion());
db914841 150 if (ExPS.IsDone())
151 {
152 if (aStartIdx == 0)
153 {
154 myNbExt = ExPS.NbExt();
155 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
156 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
157 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
158 }
159 else
160 myNbExt += ExPS.NbExt();
161
638ad7f3 162 for (i = aStartIdx + 1; i <= myNbExt; i++)
163 {
db914841 164 myPoint1->SetValue(i, myPOnC2);
165 myPoint2->SetValue(i, ExPS.Point(i - aStartIdx));
638ad7f3 166 mySqDist->SetValue(i, (myPOnC2.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value()));
db914841 167 }
168 }
638ad7f3 169 }
170
f34cd0d1 171 myDone = Standard_True;
7fd59977 172 }
173
638ad7f3 174 if (isParallel)
175 {
176 // Line direction is similar to cylinder axis of rotation.
177 // The case is possible when either extrema returned parallel status
178 // or Intersection tool returned infinite number of solutions.
179 // This is possible due to Intersection algorithm uses more precise
180 // characteristics to consider given geometries parallel.
181 // In the latter case there may be several extremas, thus we look for
182 // the one with the lowest distance and use it as a final solution.
183 mySqDist = new TColStd_HArray1OfReal(1, 1);
184 Standard_Real aDist = Extrem.SquareDistance(1);
185 const Standard_Integer aNbExt = Extrem.NbExt();
186 for (Standard_Integer i = 2; i <= aNbExt; i++)
187 {
188 const Standard_Real aD = Extrem.SquareDistance(i);
189 if (aD < aDist)
190 {
191 aDist = aD;
192 }
193 }
194
195 aDist = sqrt(aDist) - radius;
196 mySqDist->SetValue(1, aDist * aDist);
197 myDone = Standard_True;
198 myIsPar = Standard_True;
199 myNbExt = 1;
200 }
7fd59977 201}
202
203
204
205Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
206 const gp_Cone& S)
9775fa61 207{ Perform(C, S);}
7fd59977 208
209
210
211//void Extrema_ExtElCS::Perform(const gp_Lin& C,
212// const gp_Cone& S)
213void Extrema_ExtElCS::Perform(const gp_Lin& ,
214 const gp_Cone& )
215{
9775fa61 216 throw Standard_NotImplemented();
7fd59977 217
218}
219
220
221
222Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
223 const gp_Sphere& S)
224{
225 Perform(C, S);
226}
227
228
229
230void Extrema_ExtElCS::Perform(const gp_Lin& C,
db914841 231 const gp_Sphere& S)
7fd59977 232{
db914841 233 // In case of intersection - return four points:
234 // 2 intersection points and 2 perpendicular.
235 // No intersection - only min and max.
236
7fd59977 237 myDone = Standard_False;
238 myNbExt = 0;
239 myIsPar = Standard_False;
db914841 240 Standard_Integer aStartIdx = 0;
7fd59977 241
db914841 242 gp_Pnt aCenter = S.Location();
7fd59977 243
db914841 244 Extrema_ExtPElC Extrem(aCenter, C, Precision::Angular(), RealFirst(), RealLast());
7fd59977 245
246 Standard_Integer i;
db914841 247 if (Extrem.IsDone() &&
248 Extrem.NbExt() > 0)
249 {
7fd59977 250 Extrema_POnCurv myPOnC1 = Extrem.Point(1);
db914841 251 if (myPOnC1.Value().Distance(aCenter) <= S.Radius())
252 {
253 IntAna_IntConicQuad aLinSphere(C, S);
254 if (aLinSphere.IsDone())
255 {
256 myNbExt = aLinSphere.NbPoints();
257 aStartIdx = myNbExt;
258 // Not more than 2 additional points from perpendiculars.
259 mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2);
260 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2);
261 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2);
262
263 for (i = 1; i <= myNbExt; i++)
264 {
265 Extrema_POnCurv aCPnt(aLinSphere.ParamOnConic(i), aLinSphere.Point(i));
266
267 Standard_Real u,v;
268 ElSLib::Parameters(S, aLinSphere.Point(i), u, v);
269 Extrema_POnSurf aSPnt(u, v, aLinSphere.Point(i));
270
271 myPoint1->SetValue(i, aCPnt);
272 myPoint2->SetValue(i, aSPnt);
273 mySqDist->SetValue(i,(aCPnt.Value()).SquareDistance(aSPnt.Value()));
274 }
275 }
276 }
277
7fd59977 278 Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion());
db914841 279 if (ExPS.IsDone())
280 {
281 if (aStartIdx == 0)
282 {
283 myNbExt = ExPS.NbExt();
284 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
285 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
286 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
287 }
288 else
289 myNbExt += ExPS.NbExt();
290
291 for (i = aStartIdx + 1; i <= myNbExt; i++)
292 {
293 myPoint1->SetValue(i, myPOnC1);
294 myPoint2->SetValue(i, ExPS.Point(i - aStartIdx));
295 mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value()));
7fd59977 296 }
297 }
298 }
db914841 299 myDone = Standard_True;
7fd59977 300}
301
302
303Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
304 const gp_Torus& S)
9775fa61 305{ Perform(C, S);}
7fd59977 306
307
308
309//void Extrema_ExtElCS::Perform(const gp_Lin& C,
310// const gp_Torus& S)
311void Extrema_ExtElCS::Perform(const gp_Lin& ,
312 const gp_Torus& )
313{
9775fa61 314 throw Standard_NotImplemented();
7fd59977 315
316}
317
318
319// Circle-?
320
321Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
322 const gp_Pln& S)
323{
324 Perform(C, S);
325}
326
327
328
9dfbbfe6 329void Extrema_ExtElCS::Perform(const gp_Circ& C,
330 const gp_Pln& S)
7fd59977 331{
9dfbbfe6 332 myDone = Standard_True;
333 myIsPar = Standard_False;
638ad7f3 334 myNbExt = 0;
9dfbbfe6 335
336 gp_Ax2 Pos = C.Position();
337 gp_Dir NCirc = Pos.Direction();
338 gp_Dir NPln = S.Axis().Direction();
339
638ad7f3 340 Standard_Boolean isParallel = Standard_False;
9dfbbfe6 341
638ad7f3 342 if (NCirc.IsParallel(NPln, Precision::Angular())) {
343 isParallel = Standard_True;
9dfbbfe6 344 }
345 else {
346
347 gp_Dir ExtLine = NCirc ^ NPln;
348 ExtLine = ExtLine ^ NCirc;
349 //
350 gp_Dir XDir = Pos.XDirection();
351 Standard_Real T[2];
352 T[0] = XDir.AngleWithRef(ExtLine, NCirc);
353 if(T[0] < 0.)
354 {
355 //Put in period
356 T[0] += M_PI;
357 }
358 T[1] = T[0] + M_PI;
359 //
360 myNbExt = 2;
361 //Check intersection
362 IntAna_IntConicQuad anInter(C, S,
363 Precision::Angular(),
364 Precision::Confusion());
638ad7f3 365
366 if (anInter.IsDone() && anInter.IsInQuadric())
367 {
368 isParallel = Standard_True;
369 }
370 else if (anInter.IsDone())
9dfbbfe6 371 {
372 if(anInter.NbPoints() > 1)
373 {
374 myNbExt += anInter.NbPoints();
375 }
376 }
377
638ad7f3 378 if (!isParallel)
9dfbbfe6 379 {
638ad7f3 380 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
381 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
382 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
383
384 Standard_Integer i;
385 gp_Pnt PC, PP;
386 Standard_Real U, V;
387 Extrema_POnCurv POnC;
388 Extrema_POnSurf POnS;
389 for (i = 0; i < 2; ++i)
9dfbbfe6 390 {
638ad7f3 391 PC = ElCLib::CircleValue(T[i], C.Position(), C.Radius());
392 POnC.SetValues(T[i], PC);
393 myPoint1->SetValue(i + 1, POnC);
9dfbbfe6 394 ElSLib::PlaneParameters(S.Position(), PC, U, V);
395 PP = ElSLib::PlaneValue(U, V, S.Position());
396 POnS.SetParameters(U, V, PP);
638ad7f3 397 myPoint2->SetValue(i + 1, POnS);
398 mySqDist->SetValue(i + 1, PC.SquareDistance(PP));
399 }
400 //
401 if (myNbExt > 2)
402 {
403 //Add intersection points
404 for (i = 1; i <= anInter.NbPoints(); ++i)
405 {
406 Standard_Real t = anInter.ParamOnConic(i);
407 PC = ElCLib::CircleValue(t, C.Position(), C.Radius());
408 POnC.SetValues(t, PC);
409 myPoint1->SetValue(i + 2, POnC);
410 ElSLib::PlaneParameters(S.Position(), PC, U, V);
411 PP = ElSLib::PlaneValue(U, V, S.Position());
412 POnS.SetParameters(U, V, PP);
413 myPoint2->SetValue(i + 2, POnS);
414 mySqDist->SetValue(i + 2, PC.SquareDistance(PP));
415 }
9dfbbfe6 416 }
417 }
418 }
638ad7f3 419
420 if (isParallel)
421 {
422 mySqDist = new TColStd_HArray1OfReal(1, 1);
423 mySqDist->SetValue(1, S.SquareDistance(C.Location()));
424 myIsPar = Standard_True;
425 myNbExt = 1;
426 }
7fd59977 427}
428
7fd59977 429Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
430 const gp_Cylinder& S)
431{
432 Perform(C, S);
433}
434
435
436
437// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 Begin
438// Implementation of the method.
439void Extrema_ExtElCS::Perform(const gp_Circ& C,
440 const gp_Cylinder& S)
441{
442 myDone = Standard_False;
443 myIsPar = Standard_False;
444 myNbExt = 0;
445
446 // Get an axis line of the cylinder.
447 gp_Lin anAxis(S.Axis());
448
449 // Compute extrema between the circle and the line.
450 Extrema_ExtElC anExtC(anAxis, C, 0.);
451
638ad7f3 452 if (!anExtC.IsDone())
453 return;
7fd59977 454
638ad7f3 455 Standard_Boolean isParallel = Standard_False;
456
457 if (anExtC.IsParallel()) {
458 isParallel = Standard_True;
459 } else {
460 Standard_Integer aNbExt = anExtC.NbExt();
461 Standard_Integer i;
462 Standard_Integer aCurI = 1;
463 Standard_Real aTolConf = Precision::Confusion();
464 Standard_Real aCylRad = S.Radius();
465
466 // Check whether two objects have intersection points
467 IntAna_Quadric aCylQuad(S);
468 IntAna_IntConicQuad aCircCylInter(C, aCylQuad);
469 Standard_Integer aNbInter = 0;
470 if (aCircCylInter.IsDone() && aCircCylInter.IsInQuadric())
471 {
472 isParallel = Standard_True;
473 }
474 else if (aCircCylInter.IsDone())
475 {
476 aNbInter = aCircCylInter.NbPoints();
477 }
19875353 478
638ad7f3 479 if (!isParallel)
480 {
7fd59977 481 // Compute the extremas.
638ad7f3 482 myNbExt = 2 * aNbExt + aNbInter;
483 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
7fd59977 484 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
485 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
486
487 for (i = 1; i <= aNbExt; i++) {
19875353 488 Extrema_POnCurv aPOnAxis;
489 Extrema_POnCurv aPOnCirc;
490 Standard_Real aSqDist = anExtC.SquareDistance(i);
638ad7f3 491 Standard_Real aDist = sqrt(aSqDist);
19875353 492
493 anExtC.Points(i, aPOnAxis, aPOnCirc);
494
495 if (aSqDist <= (aTolConf * aTolConf)) {
496 myNbExt -= 2;
497 continue;
498 }
499
500 gp_Dir aDir(aPOnAxis.Value().XYZ().Subtracted(aPOnCirc.Value().XYZ()));
638ad7f3 501 Standard_Real aShift[2] = {aDist + aCylRad, aDist - aCylRad};
19875353 502 Standard_Integer j;
7fd59977 503
19875353 504 for (j = 0; j < 2; j++) {
505 gp_Vec aVec(aDir);
506 gp_Pnt aPntOnCyl;
7fd59977 507
19875353 508 aVec.Multiply(aShift[j]);
509 aPntOnCyl = aPOnCirc.Value().Translated(aVec);
7fd59977 510
19875353 511 Standard_Real aU;
512 Standard_Real aV;
7fd59977 513
19875353 514 ElSLib::Parameters(S, aPntOnCyl, aU, aV);
7fd59977 515
19875353 516 Extrema_POnSurf aPOnSurf(aU, aV, aPntOnCyl);
7fd59977 517
19875353 518 myPoint1->SetValue(aCurI, aPOnCirc);
519 myPoint2->SetValue(aCurI, aPOnSurf);
520 mySqDist->SetValue(aCurI++, aShift[j] * aShift[j]);
521 }
522 }
523
524 // Adding intersection points to the list of extremas
525 for (i=1; i<=aNbInter; i++)
526 {
527 Standard_Real aU;
528 Standard_Real aV;
7fd59977 529
19875353 530 gp_Pnt aInterPnt = aCircCylInter.Point(i);
7fd59977 531
19875353 532 aU = ElCLib::Parameter(C, aInterPnt);
533 Extrema_POnCurv aPOnCirc(aU, aInterPnt);
7fd59977 534
19875353 535 ElSLib::Parameters(S, aInterPnt, aU, aV);
536 Extrema_POnSurf aPOnCyl(aU, aV, aInterPnt);
537 myPoint1->SetValue(aCurI, aPOnCirc);
538 myPoint2->SetValue(aCurI, aPOnCyl);
539 mySqDist->SetValue(aCurI++, 0.0);
7fd59977 540 }
541 }
638ad7f3 542 }
7fd59977 543
638ad7f3 544 myDone = Standard_True;
545
546 if (isParallel)
547 {
548 // The case is possible when either extrema returned parallel status
549 // or Intersection tool returned infinite number of solutions.
550 // This is possible due to Intersection algorithm uses more precise
551 // characteristics to consider given geometries parallel.
552 // In the latter case there may be several extremas, thus we look for
553 // the one with the lowest distance and use it as a final solution.
554
555 myIsPar = Standard_True;
556 myNbExt = 1;
557 mySqDist = new TColStd_HArray1OfReal(1, 1);
558 Standard_Real aDist = anExtC.SquareDistance(1);
559
560 const Standard_Integer aNbExt = anExtC.NbExt();
561 for (Standard_Integer i = 2; i <= aNbExt; i++)
562 {
563 const Standard_Real aD = anExtC.SquareDistance(i);
564 if (aD < aDist)
565 {
566 aDist = aD;
567 }
568 }
569
570 aDist = sqrt(aDist) - S.Radius();
571 mySqDist->SetValue(1, aDist * aDist);
7fd59977 572 }
573}
574// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 End
575
576
577
578Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
579 const gp_Cone& S)
9775fa61 580{ Perform(C, S);}
7fd59977 581
582
583
584//void Extrema_ExtElCS::Perform(const gp_Circ& C,
585// const gp_Cone& S)
586void Extrema_ExtElCS::Perform(const gp_Circ& ,
587 const gp_Cone& )
588{
9775fa61 589 throw Standard_NotImplemented();
7fd59977 590
591}
592
593
594
03cca6f7 595//=======================================================================
596//function : Extrema_ExtElCS
597//purpose : Circle/Sphere
598//=======================================================================
7fd59977 599Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
03cca6f7 600 const gp_Sphere& S)
601{
602 Perform(C, S);
603}
604
605//=======================================================================
606//function : Perform
607//purpose : Circle/Sphere
608//=======================================================================
609void Extrema_ExtElCS::Perform(const gp_Circ& C,
610 const gp_Sphere& S)
611{
612 myDone = Standard_False;
638ad7f3 613 myIsPar = Standard_False;
614 myNbExt = 0;
03cca6f7 615
616 if (gp_Lin(C.Axis()).SquareDistance(S.Location()) < Precision::SquareConfusion())
617 {
618 // Circle and sphere are parallel
619 myIsPar = Standard_True;
620 myDone = Standard_True;
638ad7f3 621 myNbExt = 1;
7fd59977 622
03cca6f7 623 // Compute distance from circle to the sphere
624 Standard_Real aSqDistLoc = C.Location().SquareDistance(S.Location());
625 Standard_Real aSqDist = aSqDistLoc + C.Radius() * C.Radius();
626 Standard_Real aDist = sqrt(aSqDist) - S.Radius();
627 mySqDist = new TColStd_HArray1OfReal(1, 1);
628 mySqDist->SetValue(1, aDist * aDist);
629 return;
630 }
7fd59977 631
03cca6f7 632 // Intersect sphere with circle's plane
633 gp_Pln CPln(C.Location(), C.Axis().Direction());
634 IntAna_QuadQuadGeo anInter(CPln, S);
635 if (!anInter.IsDone())
636 // not done
637 return;
7fd59977 638
03cca6f7 639 if (anInter.TypeInter() != IntAna_Circle)
640 {
641 // Intersection is empty or just a point.
642 // The parallel case has already been considered,
643 // thus, here we have to find only one minimal solution
644 myNbExt = 1;
645 myDone = Standard_True;
646
647 mySqDist = new TColStd_HArray1OfReal(1, 1);
648 myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1);
649 myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1);
650
651 // Compute parameter on circle
652 const Standard_Real aT = ElCLib::Parameter(C, S.Location());
653 // Compute point on circle
654 gp_Pnt aPOnC = ElCLib::Value(aT, C);
655
656 // Compute parameters on sphere
657 Standard_Real aU, aV;
658 ElSLib::Parameters(S, aPOnC, aU, aV);
659 // Compute point on sphere
660 gp_Pnt aPOnS = ElSLib::Value(aU, aV, S);
661
662 // Save solution
663 myPoint1->SetValue(1, Extrema_POnCurv(aT, aPOnC));
664 myPoint2->SetValue(1, Extrema_POnSurf(aU, aV, aPOnS));
665 mySqDist->SetValue(1, aPOnC.SquareDistance(aPOnS));
666 return;
667 }
668
669 // Here, the intersection is a circle
670
671 // Intersection circle
672 gp_Circ aCInt = anInter.Circle(1);
673
674 // Perform intersection of the input circle with the intersection circle
675 Extrema_ExtElC anExtC(C, aCInt);
676 Standard_Boolean isExtremaCircCircValid = anExtC.IsDone() // Check if intersection is done
677 && !anExtC.IsParallel() // Parallel case has already been considered
678 && anExtC.NbExt() > 0; // Check that some solutions have been found
679 if (!isExtremaCircCircValid)
680 // not done
681 return;
682
683 myDone = Standard_True;
684
685 // Few solutions
686 Standard_Real aNbExt = anExtC.NbExt();
687 // Find the minimal distance
688 Standard_Real aMinSqDist = ::RealLast();
689 for (Standard_Integer i = 1; i <= aNbExt; ++i)
690 {
691 Standard_Real aSqDist = anExtC.SquareDistance(i);
692 if (aSqDist < aMinSqDist)
693 aMinSqDist = aSqDist;
694 }
7fd59977 695
03cca6f7 696 // Collect all solutions close to the minimal one
697 TColStd_ListOfInteger aSols;
698 for (Standard_Integer i = 1; i <= aNbExt; ++i)
699 {
700 Standard_Real aDiff = anExtC.SquareDistance(i) - aMinSqDist;
701 if (aDiff < Precision::SquareConfusion())
702 aSols.Append(i);
703 }
704
705 // Save all minimal solutions
706 myNbExt = aSols.Extent();
707
708 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
709 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
710 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
711
712 TColStd_ListIteratorOfListOfInteger it(aSols);
713 for (Standard_Integer iSol = 1; it.More(); it.Next(), ++iSol)
714 {
715 Extrema_POnCurv P1, P2;
716 anExtC.Points(it.Value(), P1, P2);
717
718 // Compute parameters on sphere
719 Standard_Real aU, aV;
720 ElSLib::Parameters(S, P1.Value(), aU, aV);
721 // Compute point on sphere
722 gp_Pnt aPOnS = ElSLib::Value(aU, aV, S);
723
724 // Save solution
725 myPoint1->SetValue(iSol, P1);
726 myPoint2->SetValue(iSol, Extrema_POnSurf(aU, aV, aPOnS));
727 mySqDist->SetValue(iSol, P1.Value().SquareDistance(aPOnS));
728 }
7fd59977 729}
730
731Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
732 const gp_Torus& S)
9775fa61 733{ Perform(C, S);}
7fd59977 734
735
736
737//void Extrema_ExtElCS::Perform(const gp_Circ& C,
738// const gp_Torus& S)
739void Extrema_ExtElCS::Perform(const gp_Circ& ,
740 const gp_Torus& )
741{
9775fa61 742 throw Standard_NotImplemented();
7fd59977 743
744}
745
746Extrema_ExtElCS::Extrema_ExtElCS(const gp_Hypr& C,
747 const gp_Pln& S)
748{
749 Perform(C, S);
750}
751
752
753
754void Extrema_ExtElCS::Perform(const gp_Hypr& C,
755 const gp_Pln& S)
756{
757 myDone = Standard_True;
758 myIsPar = Standard_False;
638ad7f3 759 myNbExt = 0;
7fd59977 760
761 gp_Ax2 Pos = C.Position();
762 gp_Dir NHypr = Pos.Direction();
763 gp_Dir NPln = S.Axis().Direction();
764
765 if (NHypr.IsParallel(NPln, Precision::Angular())) {
766
767 mySqDist = new TColStd_HArray1OfReal(1, 1);
768 mySqDist->SetValue(1, S.SquareDistance(C.Location()));
769 myIsPar = Standard_True;
638ad7f3 770 myNbExt = 1;
7fd59977 771 }
772 else {
773
774 gp_Dir XDir = Pos.XDirection();
775 gp_Dir YDir = Pos.YDirection();
776
777 Standard_Real A = C.MinorRadius()*(NPln.Dot(YDir));
778 Standard_Real B = C.MajorRadius()*(NPln.Dot(XDir));
779
780 if(Abs(B) > Abs(A)) {
781 Standard_Real T = -0.5 * Log((A+B)/(B-A));
782 gp_Pnt Ph = ElCLib::HyperbolaValue(T, Pos, C.MajorRadius(), C.MinorRadius());
783 Extrema_POnCurv PC(T, Ph);
784 myPoint1 = new Extrema_HArray1OfPOnCurv(1,1);
785 myPoint1->SetValue(1, PC);
786
787 mySqDist = new TColStd_HArray1OfReal(1, 1);
788 mySqDist->SetValue(1, S.SquareDistance(Ph));
789
790 Standard_Real U, V;
791 ElSLib::PlaneParameters(S.Position(), Ph, U, V);
792 gp_Pnt Pp = ElSLib::PlaneValue(U, V, S.Position());
793 Extrema_POnSurf PS(U, V, Pp);
794 myPoint2 = new Extrema_HArray1OfPOnSurf(1,1);
795 myPoint2->SetValue(1, PS);
796
797 myNbExt = 1;
798 }
7fd59977 799 }
7fd59977 800}
801
802
803Standard_Boolean Extrema_ExtElCS::IsDone() const
804{
805 return myDone;
806}
807
808
809Standard_Integer Extrema_ExtElCS::NbExt() const
810{
638ad7f3 811 if (!IsDone()) throw StdFail_NotDone();
7fd59977 812 return myNbExt;
813}
814
815Standard_Real Extrema_ExtElCS::SquareDistance(const Standard_Integer N) const
816{
638ad7f3 817 if (N < 1 || N > NbExt())
818 {
819 throw Standard_OutOfRange();
820 }
821
7fd59977 822 return mySqDist->Value(N);
823}
824
825
826void Extrema_ExtElCS::Points(const Standard_Integer N,
827 Extrema_POnCurv& P1,
828 Extrema_POnSurf& P2) const
829{
638ad7f3 830 if (IsParallel())
831 {
832 throw StdFail_InfiniteSolutions();
833 }
834
835 if (N < 1 || N > NbExt())
836 {
837 throw Standard_OutOfRange();
838 }
839
7fd59977 840 P1 = myPoint1->Value(N);
841 P2 = myPoint2->Value(N);
842}
843
844
845Standard_Boolean Extrema_ExtElCS::IsParallel() const
846{
638ad7f3 847 if (!IsDone())
848 {
849 throw StdFail_NotDone();
850 }
7fd59977 851 return myIsPar;
852}