1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <Extrema_ExtPElS.ixx>
16 #include <StdFail_NotDone.hxx>
17 #include <Standard_OutOfRange.hxx>
18 #include <Standard_NotImplemented.hxx>
20 static const Standard_Real ExtPElS_MyEps = Epsilon(2. * M_PI);
21 //=============================================================================
23 Extrema_ExtPElS::Extrema_ExtPElS () { myDone = Standard_False; }
24 //=============================================================================
26 Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
28 const Standard_Real Tol)
33 /*-----------------------------------------------------------------------------
35 Find 2 extreme distances between point P and cylinder S.
38 Let Pp be the projection of P in plane XOY of the cylinder;
39 2 cases are considered:
40 1- distance(Pp,O) < Tol:
41 There are infinite solutions; IsDone() = Standard_False.
42 2- distance(Pp,O) > Tol:
44 U1 = angle(OX,OPp) with 0 < U1 < 2.*M_PI
45 U2 = U1 + M_PI with 0 < U2 < 2.*M_PI;
46 then (U1,V) corresponds to the min distance.
47 and (U2,V) corresponds to the max distance.
48 -----------------------------------------------------------------------------*/
50 void Extrema_ExtPElS::Perform(const gp_Pnt& P,
52 const Standard_Real Tol)
54 myDone = Standard_False;
57 // Projection of point P in plane XOY of the cylinder ...
58 gp_Ax3 Pos = S.Position();
59 gp_Pnt O = Pos.Location();
60 gp_Vec OZ (Pos.Direction());
61 Standard_Real V = gp_Vec(O,P).Dot(OZ);
62 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
64 // Calculation of extrema
66 if (OPp.Magnitude() < Tol) { return; }
67 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
68 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-M_PI<U1<M_PI
69 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
70 Standard_Real U2 = U1 + M_PI;
71 if (U1 < 0.) { U1 += 2. * M_PI; }
74 Ps = ElSLib::Value(U1,V,S);
75 mySqDist[0] = Ps.SquareDistance(P);
76 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
77 Ps = ElSLib::Value(U2,V,S);
78 mySqDist[1] = Ps.SquareDistance(P);
79 myPoint[1] = Extrema_POnSurf(U2,V,Ps);
82 myDone = Standard_True;
84 //=============================================================================
86 Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
88 const Standard_Real Tol)
92 /*-----------------------------------------------------------------------------
94 Find 2 extreme distances between point P and cone S.
97 Let M the top of the cone.
98 2 cases are considered:
99 1- distance(P,M) < Tol:
100 there is a minimum in M.
101 2- distance(P,M) > Tol:
102 Let Pp the projection of P in the plane XOY of the cone;
103 2 cases are considered:
104 1- distance(Pp,O) < Tol:
105 There is an infinite number of solutions; IsDone() = Standard_False.
106 2- distance(Pp,O) > Tol:
107 There exist 2 extrema:
108 Let Vm = value of v for point M,
109 Vp = value of v for point P,
110 U1 = angle(OX,OPp) if Vp > Vm )
111 -angle(OX,OPp) otherwise ) with 0. < U1 < 2*M_PI,
112 U2 = U1 + M_PI with 0. < U2 < 2*M_PI;
113 We are in plane PpOZ.
114 Let A the angle of the cone,
115 B = angle(MP,MO) with 0. < B < M_PI,
117 V1 = (L * cos(B-A)) + Vm,
118 V2 = (L * cos(B+A)) + Vm;
119 then (U1,V1) and (U2,V2) correspond to min distances.
120 -----------------------------------------------------------------------------*/
122 void Extrema_ExtPElS::Perform(const gp_Pnt& P,
124 const Standard_Real Tol)
126 myDone = Standard_False;
130 gp_Ax3 Pos = S.Position();
131 gp_Pnt O = Pos.Location();
132 Standard_Real A = S.SemiAngle();
133 gp_Vec OZ (Pos.Direction());
134 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
137 Standard_Real L2 = MP.SquareMagnitude();
138 Standard_Real Vm = -(S.RefRadius() / Sin(A));
140 // Case when P is mixed with S ...
141 if (L2 < Tol * Tol) {
143 myPoint[0] = Extrema_POnSurf(0.,Vm,M);
145 myDone = Standard_True;
149 if (M.SquareDistance(O)<Tol * Tol)
151 if( A<0) DirZ.Multiplied(-1.);
155 // Projection of P in the reference plane of the cone ...
156 Standard_Real Zp = gp_Vec(O, P).Dot(OZ);
158 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
160 if (OPp.SquareMagnitude() < Tol * Tol) return;
161 Standard_Real B, U1, V1, U2, V2;
162 Standard_Boolean Same = DirZ.Dot(MP) >= 0.0;
163 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-M_PI<U1<M_PI
164 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
166 if (!Same) { U1 += M_PI; }
168 if (U1 < 0.) { U1 += 2. * M_PI; }
169 if (U2 > 2.*M_PI) { U2 -= 2. * M_PI; }
172 Standard_Real L = sqrt(L2);
182 Standard_Real Sense = OZ.Dot(gp_Dir(DirZ));
183 V1 *= Sense; V2 *= Sense;
187 Ps = ElSLib::Value(U1,V1,S);
188 mySqDist[0] = Ps.SquareDistance(P);
189 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
190 Ps = ElSLib::Value(U2,V2,S);
191 mySqDist[1] = Ps.SquareDistance(P);
192 myPoint[1] = Extrema_POnSurf(U2,V2,Ps);
195 myDone = Standard_True;
197 //=============================================================================
199 Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
201 const Standard_Real Tol)
205 /*-----------------------------------------------------------------------------
207 Find 2 extreme distances between point P and sphere S.
210 Let O be the origin of the sphere.
211 2 cases are considered:
212 1- distance(P,O) < Tol:
213 There is an infinite number of solutions; IsDone() = Standard_False
214 2- distance(P,O) > Tol:
215 Let Pp be the projection of point P in the plane XOY of the sphere;
216 2 cases are considered:
217 1- distance(Pp,O) < Tol:
218 2 solutions are: (0,-M_PI/2.) and (0.,M_PI/2.)
219 2- distance(Pp,O) > Tol:
220 Let U1 = angle(OX,OPp) with 0. < U1 < 2.*M_PI,
221 U2 = U1 + M_PI avec 0. < U2 < 2*M_PI,
222 V1 = angle(OPp,OP) with -M_PI/2. < V1 < M_PI/2. ,
223 then (U1, V1) corresponds to the min distance
224 and (U2,-V1) corresponds to the max distance.
225 -----------------------------------------------------------------------------*/
227 void Extrema_ExtPElS::Perform(const gp_Pnt& P,
229 const Standard_Real Tol)
231 myDone = Standard_False;
234 gp_Ax3 Pos = S.Position();
235 gp_Vec OP (Pos.Location(),P);
237 // Case when P is mixed with O ...
238 if (OP.SquareMagnitude() < Tol * Tol) { return; }
240 // Projection if P in plane XOY of the sphere ...
241 gp_Pnt O = Pos.Location();
242 gp_Vec OZ (Pos.Direction());
243 Standard_Real Zp = OP.Dot(OZ);
244 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
246 // Calculation of extrema ...
248 Standard_Real U1, U2, V;
249 if (OPp.SquareMagnitude() < Tol * Tol) {
252 if (Zp < 0.) { V = -M_PI / 2.; }
253 else { V = M_PI / 2.; }
256 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
257 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
258 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
260 if (U1 < 0.) { U1 += 2. * M_PI; }
262 if (Zp < 0.) { V = -V; }
266 Ps = ElSLib::Value(U1,V,S);
267 mySqDist[0] = Ps.SquareDistance(P);
268 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
269 Ps = ElSLib::Value(U2,-V,S);
270 mySqDist[1] = Ps.SquareDistance(P);
271 myPoint[1] = Extrema_POnSurf(U2,-V,Ps);
274 myDone = Standard_True;
276 //=============================================================================
278 Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
280 const Standard_Real Tol)
284 /*-----------------------------------------------------------------------------
286 Find 2 extreme distances between point P and torus S.
289 Let Pp be the projection of point P in plane XOY of the torus;
290 2 cases are consideres:
291 1- distance(Pp,O) < Tol:
292 There is an infinite number of solutions; IsDone() = Standard_False.
293 2- distance(Pp,O) > Tol:
294 One is located in plane PpOZ;
295 Let V1 = angle(OX,OPp) with 0. < V1 < 2.*M_PI,
296 V2 = V1 + M_PI with 0. < V2 < 2.*M_PI,
297 O1 and O2 centers of circles (O1 on coord. posit.)
300 then (U1,V1) corresponds to the min distance
301 and (U2,V2) corresponds to the max distance.
302 -----------------------------------------------------------------------------*/
303 void Extrema_ExtPElS::Perform(const gp_Pnt& P,
305 const Standard_Real Tol)
307 myDone = Standard_False;
310 // Projection of P in plane XOY ...
311 gp_Ax3 Pos = S.Position();
312 gp_Pnt O = Pos.Location();
313 gp_Vec OZ (Pos.Direction());
314 gp_Pnt Pp = P.Translated(OZ.Multiplied(-(gp_Vec(O,P).Dot(Pos.Direction()))));
316 // Calculation of extrema ...
318 Standard_Real R2 = OPp.SquareMagnitude();
319 if (R2 < Tol * Tol) { return; }
321 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
322 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
323 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
324 Standard_Real U2 = U1 + M_PI;
325 if (U1 < 0.) { U1 += 2. * M_PI; }
326 Standard_Real R = sqrt(R2);
327 gp_Vec OO1 = OPp.Divided(R).Multiplied(S.MajorRadius());
328 gp_Vec OO2 = OO1.Multiplied(-1.);
329 gp_Pnt O1 = O.Translated(OO1);
330 gp_Pnt O2 = O.Translated(OO2);
332 if(O1.SquareDistance(P) < Tol) { return; }
333 if(O2.SquareDistance(P) < Tol) { return; }
335 Standard_Real V1 = OO1.AngleWithRef(gp_Vec(O1,P),OO1.Crossed(OZ));
336 if (V1 > -ExtPElS_MyEps && V1 < ExtPElS_MyEps) { V1 = 0.; }
337 Standard_Real V2 = OO2.AngleWithRef(gp_Vec(P,O2),OO2.Crossed(OZ));
338 if (V2 > -ExtPElS_MyEps && V2 < ExtPElS_MyEps) { V2 = 0.; }
340 if (V1 < 0.) { V1 += 2. * M_PI; }
341 if (V2 < 0.) { V2 += 2. * M_PI; }
344 Ps = ElSLib::Value(U1,V1,S);
345 mySqDist[0] = Ps.SquareDistance(P);
346 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
348 Ps = ElSLib::Value(U1,V1+M_PI,S);
349 mySqDist[1] = Ps.SquareDistance(P);
350 myPoint[1] = Extrema_POnSurf(U1,V1+M_PI,Ps);
352 Ps = ElSLib::Value(U2,V2,S);
353 mySqDist[2] = Ps.SquareDistance(P);
354 myPoint[2] = Extrema_POnSurf(U2,V2,Ps);
356 Ps = ElSLib::Value(U2,V2+M_PI,S);
357 mySqDist[3] = Ps.SquareDistance(P);
358 myPoint[3] = Extrema_POnSurf(U2,V2+M_PI,Ps);
361 myDone = Standard_True;
365 Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
367 const Standard_Real Tol)
372 void Extrema_ExtPElS::Perform (const gp_Pnt& P,
374 // const Standard_Real Tol)
375 const Standard_Real )
377 myDone = Standard_False;
380 // Projection of point P in plane XOY of the cylinder ...
381 gp_Pnt O = S.Location();
382 gp_Vec OZ (S.Axis().Direction());
383 Standard_Real U, V = gp_Vec(O,P).Dot(OZ);
384 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
386 ElSLib::Parameters(S, P, U, V);
387 mySqDist[0] = Pp.SquareDistance(P);
388 myPoint[0] = Extrema_POnSurf(U,V,Pp);
390 myDone = Standard_True;
394 //=============================================================================
396 Standard_Boolean Extrema_ExtPElS::IsDone () const { return myDone; }
397 //=============================================================================
399 Standard_Integer Extrema_ExtPElS::NbExt () const
401 if (!IsDone()) { StdFail_NotDone::Raise(); }
404 //=============================================================================
406 Standard_Real Extrema_ExtPElS::SquareDistance (const Standard_Integer N) const
408 if (!IsDone()) { StdFail_NotDone::Raise(); }
409 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
410 return mySqDist[N-1];
412 //=============================================================================
414 const Extrema_POnSurf& Extrema_ExtPElS::Point (const Standard_Integer N) const
416 if (!IsDone()) { StdFail_NotDone::Raise(); }
417 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
420 //=============================================================================