summaryrefslogtreecommitdiff
path: root/inc/Extrema_ExtPSOfRev.gxx
blob: 647708a70e84b4edf56680ceff18be8aea35f531 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <StdFail_NotDone.hxx>
#include <Standard_OutOfRange.hxx>
//=============================================================================

Extrema_ExtPSOfRev::Extrema_ExtPSOfRev (const gp_Pnt& P,
			      const SurfaceOfRevolution& S,
			      const Standard_Real Tol,
			      const Standard_Integer NbV, const Standard_Real TolV)
/*-----------------------------------------------------------------------------
Fonction:
   Recherche de toutes les distances extremales entre le point P et la surface
  de revolution S.

Methode:
   Soit Pp la projection du point P dans le plan XOY de la surface S;
  2 cas sont consideres:
  1- distance(Pp,O) < Tol:
     Il existe 0 ou une infinite de solutions; IsDone() = Standard_False;
  2- distance(Pp,O) > Tol:
     Soit U1 = angle(OX,OPp) avec 0. < U1 < 2.*PI,
          U2 = U1 + PI       avec 0. < U2 < 2.*PI,
          M1 le meridien S(U1),
	  M2 le meridien S(U2);
     On recherche les distances minimales entre P et M1 et les distances
     maximales entre P et M2. Soit {V1i,i=1,n} et {V2j, j=1,m} ces solutions;
     alors les (U1,V1i) correspondent a des distances minimales
     et    les (U2,V2j) correspondent a des distances maximales.
-----------------------------------------------------------------------------*/
{
  myDone = Standard_False;

// Projection de P dans le plan XOY de la surface de revolution ...
  gp_Ax3 Pos = Tool::Position(S);
  gp_Pnt O = Pos.Location();
  gp_Vec OZ (Pos.Direction());
  gp_Pnt Pp = P.Translated(OZ.Multiplied(-(gp_Vec(O,P).Dot(OZ))));
  gp_Vec OPp (O,Pp);
  if (OPp.Magnitude() < Tol) { return; }

  Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,OZ);
  Standard_Real U2 = U1 + PI;
  if (U1 < 0.) { U1 += 2. * PI; }
  Curve M1 = Tool::Meridian(S, U1);
  Curve M2 = Tool::Meridian(S, U2);
  TheExtPC ExtPM1 (P,M1,NbV,TolV,Tol);
  TheExtPC ExtPM2 (P,M2,NbV,TolV,Tol);
  if ((ExtPM1.IsDone()) && (ExtPM2.IsDone())) {
    Standard_Integer NbExt1 = ExtPM1.NbExt();
    Standard_Integer NbExt2 = ExtPM2.NbExt();
    Extrema_POnCurv ExtPM;
    for (Standard_Integer NoExt = 1; NoExt <= NbExt1; NoExt++) {
      if (ExtPM1.IsMin(NoExt)) {
	ExtPM = ExtPM1.Point(NoExt);
	mySqDist.Append(ExtPM1.SquareDistance(NoExt));
	myPoint.Append(Extrema_POnSurf(U1,ExtPM.Parameter(),ExtPM.SquareDistance()));
      }
    }
    for (NoExt = 1; NoExt <= NbExt2; NoExt++) {
      if (!ExtPM2.IsMin(NoExt)) {
	ExtPM = ExtPM2.Point(NoExt);
	mySqDist.Append(ExtPM2.SquareDistance(NoExt));
	myPoint.Append(Extrema_POnSurf(U2,ExtPM.Parameter(),ExtPM.SquareDistance()));
      }
    }
    myDone = Standard_True;
  }
}
//=============================================================================

Standard_Boolean Extrema_ExtPSOfRev::IsDone () const { return myDone; }
//=============================================================================

Standard_Integer Extrema_ExtPSOfRev::NbExt () const
{
  if (!IsDone()) { StdFail_NotDone::Raise(); }
  return mySqDist.Length();
}
//=============================================================================

Standard_Real Extrema_ExtPSOfRev::SquareDistance (const Standard_Integer N) const
{
  if (!IsDone()) { StdFail_NotDone::Raise(); }
  return mySqDist.Value(N);
}
//=============================================================================

Extrema_POnSurf Extrema_ExtPSOfRev::Point (const Standard_Integer N) const
{
  if (!IsDone()) { StdFail_NotDone::Raise(); }
  return myPoint.Value(N);
}
//=============================================================================