Warnings on vc14 were eliminated
[occt.git] / src / Extrema / Extrema_ExtPElS.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.
b311480e 14
42cf5bc1 15
7fd59977 16#include <ElSLib.hxx>
42cf5bc1 17#include <Extrema_ExtPElS.hxx>
18#include <Extrema_POnSurf.hxx>
19#include <gp_Cone.hxx>
20#include <gp_Cylinder.hxx>
21#include <gp_Pln.hxx>
22#include <gp_Pnt.hxx>
23#include <gp_Sphere.hxx>
24#include <gp_Torus.hxx>
25#include <Standard_NotImplemented.hxx>
26#include <Standard_OutOfRange.hxx>
27#include <StdFail_NotDone.hxx>
28
7c4e9501 29static const Standard_Real ExtPElS_MyEps = Epsilon(2. * M_PI);
7fd59977 30//=============================================================================
31
32Extrema_ExtPElS::Extrema_ExtPElS () { myDone = Standard_False; }
33//=============================================================================
34
35Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
36 const gp_Cylinder& S,
37 const Standard_Real Tol)
38{
39
40 Perform(P, S, Tol);
41}
42/*-----------------------------------------------------------------------------
0d969553
Y
43Function:
44Find 2 extreme distances between point P and cylinder S.
7fd59977 45
0d969553
Y
46Method:
47 Let Pp be the projection of P in plane XOY of the cylinder;
48 2 cases are considered:
7fd59977 49 1- distance(Pp,O) < Tol:
0d969553 50 There are infinite solutions; IsDone() = Standard_False.
7fd59977 51 2- distance(Pp,O) > Tol:
0d969553 52 let V = OP.OZ,
c6541a0c
D
53 U1 = angle(OX,OPp) with 0 < U1 < 2.*M_PI
54 U2 = U1 + M_PI with 0 < U2 < 2.*M_PI;
0d969553
Y
55 then (U1,V) corresponds to the min distance.
56 and (U2,V) corresponds to the max distance.
7fd59977 57-----------------------------------------------------------------------------*/
58
59void Extrema_ExtPElS::Perform(const gp_Pnt& P,
60 const gp_Cylinder& S,
61 const Standard_Real Tol)
62{
63 myDone = Standard_False;
64 myNbExt = 0;
65
0d969553 66// Projection of point P in plane XOY of the cylinder ...
7fd59977 67 gp_Ax3 Pos = S.Position();
68 gp_Pnt O = Pos.Location();
69 gp_Vec OZ (Pos.Direction());
70 Standard_Real V = gp_Vec(O,P).Dot(OZ);
71 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
72
0d969553 73// Calculation of extrema
7fd59977 74 gp_Vec OPp (O,Pp);
75 if (OPp.Magnitude() < Tol) { return; }
76 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
c6541a0c 77 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-M_PI<U1<M_PI
7c4e9501 78 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
c6541a0c
D
79 Standard_Real U2 = U1 + M_PI;
80 if (U1 < 0.) { U1 += 2. * M_PI; }
7fd59977 81
82 gp_Pnt Ps;
83 Ps = ElSLib::Value(U1,V,S);
84 mySqDist[0] = Ps.SquareDistance(P);
85 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
86 Ps = ElSLib::Value(U2,V,S);
87 mySqDist[1] = Ps.SquareDistance(P);
88 myPoint[1] = Extrema_POnSurf(U2,V,Ps);
89
90 myNbExt = 2;
91 myDone = Standard_True;
92}
93//=============================================================================
94
95Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
96 const gp_Cone& S,
97 const Standard_Real Tol)
98{
99 Perform(P, S, Tol);
100}
101/*-----------------------------------------------------------------------------
0d969553
Y
102Function:
103 Find 2 extreme distances between point P and cone S.
7fd59977 104
0d969553
Y
105Method:
106 Let M the top of the cone.
107 2 cases are considered:
7fd59977 108 1- distance(P,M) < Tol:
0d969553 109 there is a minimum in M.
7fd59977 110 2- distance(P,M) > Tol:
0d969553
Y
111 Let Pp the projection of P in the plane XOY of the cone;
112 2 cases are considered:
7fd59977 113 1- distance(Pp,O) < Tol:
0d969553 114 There is an infinite number of solutions; IsDone() = Standard_False.
7fd59977 115 2- distance(Pp,O) > Tol:
0d969553
Y
116 There exist 2 extrema:
117 Let Vm = value of v for point M,
118 Vp = value of v for point P,
119 U1 = angle(OX,OPp) if Vp > Vm )
c6541a0c
D
120 -angle(OX,OPp) otherwise ) with 0. < U1 < 2*M_PI,
121 U2 = U1 + M_PI with 0. < U2 < 2*M_PI;
0d969553
Y
122 We are in plane PpOZ.
123 Let A the angle of the cone,
c6541a0c 124 B = angle(MP,MO) with 0. < B < M_PI,
7fd59977 125 L = longueur(MP),
126 V1 = (L * cos(B-A)) + Vm,
127 V2 = (L * cos(B+A)) + Vm;
0d969553 128 then (U1,V1) and (U2,V2) correspond to min distances.
7fd59977 129-----------------------------------------------------------------------------*/
130
131void Extrema_ExtPElS::Perform(const gp_Pnt& P,
132 const gp_Cone& S,
133 const Standard_Real Tol)
134{
135 myDone = Standard_False;
136 myNbExt = 0;
137
138 gp_Pnt M = S.Apex();
139 gp_Ax3 Pos = S.Position();
140 gp_Pnt O = Pos.Location();
141 Standard_Real A = S.SemiAngle();
142 gp_Vec OZ (Pos.Direction());
143 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
144 gp_Vec MP (M,P);
145
146 Standard_Real L2 = MP.SquareMagnitude();
147 Standard_Real Vm = -(S.RefRadius() / Sin(A));
7fd59977 148
0d969553 149// Case when P is mixed with S ...
7fd59977 150 if (L2 < Tol * Tol) {
151 mySqDist[0] = L2;
152 myPoint[0] = Extrema_POnSurf(0.,Vm,M);
153 myNbExt = 1;
154 myDone = Standard_True;
155 return;
156 }
157 gp_Vec DirZ;
158 if (M.SquareDistance(O)<Tol * Tol)
159 { DirZ=OZ;
160 if( A<0) DirZ.Multiplied(-1.);
161 }
162 else
163 DirZ=gp_Vec(M,O);
0d969553 164// Projection of P in the reference plane of the cone ...
7fd59977 165 Standard_Real Zp = gp_Vec(O, P).Dot(OZ);
166
167 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
168 gp_Vec OPp(O, Pp);
169 if (OPp.SquareMagnitude() < Tol * Tol) return;
170 Standard_Real B, U1, V1, U2, V2;
171 Standard_Boolean Same = DirZ.Dot(MP) >= 0.0;
c6541a0c 172 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-M_PI<U1<M_PI
7c4e9501 173 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
7fd59977 174 B = MP.Angle(DirZ);
c6541a0c
D
175 if (!Same) { U1 += M_PI; }
176 U2 = U1 + M_PI;
177 if (U1 < 0.) { U1 += 2. * M_PI; }
178 if (U2 > 2.*M_PI) { U2 -= 2. * M_PI; }
7fd59977 179 B = MP.Angle(DirZ);
180 A = Abs(A);
181 Standard_Real L = sqrt(L2);
182 if (!Same) {
c6541a0c 183 B = M_PI-B;
7fd59977 184 V1 = -L*cos(B-A);
185 V2 = -L*cos(B+A);
186 }
187 else {
188 V1 = L * cos(B-A);
189 V2 = L * cos(B+A);
190 }
191 Standard_Real Sense = OZ.Dot(gp_Dir(DirZ));
192 V1 *= Sense; V2 *= Sense;
193 V1 += Vm; V2 += Vm;
194
195 gp_Pnt Ps;
196 Ps = ElSLib::Value(U1,V1,S);
197 mySqDist[0] = Ps.SquareDistance(P);
198 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
199 Ps = ElSLib::Value(U2,V2,S);
200 mySqDist[1] = Ps.SquareDistance(P);
201 myPoint[1] = Extrema_POnSurf(U2,V2,Ps);
202
203 myNbExt = 2;
204 myDone = Standard_True;
205}
206//=============================================================================
207
208Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
209 const gp_Sphere& S,
210 const Standard_Real Tol)
211{
212 Perform(P, S, Tol);
213}
214/*-----------------------------------------------------------------------------
0d969553
Y
215Function:
216 Find 2 extreme distances between point P and sphere S.
7fd59977 217
0d969553
Y
218Method:
219 Let O be the origin of the sphere.
220 2 cases are considered:
7fd59977 221 1- distance(P,O) < Tol:
0d969553 222 There is an infinite number of solutions; IsDone() = Standard_False
7fd59977 223 2- distance(P,O) > Tol:
0d969553
Y
224 Let Pp be the projection of point P in the plane XOY of the sphere;
225 2 cases are considered:
7fd59977 226 1- distance(Pp,O) < Tol:
c6541a0c 227 2 solutions are: (0,-M_PI/2.) and (0.,M_PI/2.)
7fd59977 228 2- distance(Pp,O) > Tol:
c6541a0c
D
229 Let U1 = angle(OX,OPp) with 0. < U1 < 2.*M_PI,
230 U2 = U1 + M_PI avec 0. < U2 < 2*M_PI,
231 V1 = angle(OPp,OP) with -M_PI/2. < V1 < M_PI/2. ,
0d969553
Y
232 then (U1, V1) corresponds to the min distance
233 and (U2,-V1) corresponds to the max distance.
7fd59977 234-----------------------------------------------------------------------------*/
235
236void Extrema_ExtPElS::Perform(const gp_Pnt& P,
237 const gp_Sphere& S,
238 const Standard_Real Tol)
239{
240 myDone = Standard_False;
241 myNbExt = 0;
242
243 gp_Ax3 Pos = S.Position();
244 gp_Vec OP (Pos.Location(),P);
245
0d969553 246// Case when P is mixed with O ...
7fd59977 247 if (OP.SquareMagnitude() < Tol * Tol) { return; }
248
0d969553 249// Projection if P in plane XOY of the sphere ...
7fd59977 250 gp_Pnt O = Pos.Location();
251 gp_Vec OZ (Pos.Direction());
252 Standard_Real Zp = OP.Dot(OZ);
253 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
254
0d969553 255// Calculation of extrema ...
7fd59977 256 gp_Vec OPp (O,Pp);
257 Standard_Real U1, U2, V;
258 if (OPp.SquareMagnitude() < Tol * Tol) {
259 U1 = 0.;
260 U2 = 0.;
c6541a0c
D
261 if (Zp < 0.) { V = -M_PI / 2.; }
262 else { V = M_PI / 2.; }
7fd59977 263 }
264 else {
265 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
266 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
7c4e9501 267 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
c6541a0c
D
268 U2 = U1 + M_PI;
269 if (U1 < 0.) { U1 += 2. * M_PI; }
7fd59977 270 V = OP.Angle(OPp);
271 if (Zp < 0.) { V = -V; }
272 }
273
274 gp_Pnt Ps;
275 Ps = ElSLib::Value(U1,V,S);
276 mySqDist[0] = Ps.SquareDistance(P);
277 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
278 Ps = ElSLib::Value(U2,-V,S);
279 mySqDist[1] = Ps.SquareDistance(P);
280 myPoint[1] = Extrema_POnSurf(U2,-V,Ps);
281
282 myNbExt = 2;
283 myDone = Standard_True;
284}
285//=============================================================================
286
287Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
288 const gp_Torus& S,
289 const Standard_Real Tol)
290{
291 Perform(P, S, Tol);
292}
293/*-----------------------------------------------------------------------------
0d969553
Y
294Function:
295 Find 2 extreme distances between point P and torus S.
7fd59977 296
0d969553
Y
297 Method:
298 Let Pp be the projection of point P in plane XOY of the torus;
299 2 cases are consideres:
7fd59977 300 1- distance(Pp,O) < Tol:
0d969553 301 There is an infinite number of solutions; IsDone() = Standard_False.
7fd59977 302 2- distance(Pp,O) > Tol:
0d969553 303 One is located in plane PpOZ;
c6541a0c
D
304 Let V1 = angle(OX,OPp) with 0. < V1 < 2.*M_PI,
305 V2 = V1 + M_PI with 0. < V2 < 2.*M_PI,
0d969553
Y
306 O1 and O2 centers of circles (O1 on coord. posit.)
307 U1 = angle(OPp,O1P),
308 U2 = angle(OPp,PO2);
309 then (U1,V1) corresponds to the min distance
310 and (U2,V2) corresponds to the max distance.
7fd59977 311-----------------------------------------------------------------------------*/
312void Extrema_ExtPElS::Perform(const gp_Pnt& P,
313 const gp_Torus& S,
314 const Standard_Real Tol)
315{
316 myDone = Standard_False;
317 myNbExt = 0;
318
0d969553 319// Projection of P in plane XOY ...
7fd59977 320 gp_Ax3 Pos = S.Position();
321 gp_Pnt O = Pos.Location();
322 gp_Vec OZ (Pos.Direction());
323 gp_Pnt Pp = P.Translated(OZ.Multiplied(-(gp_Vec(O,P).Dot(Pos.Direction()))));
324
0d969553 325// Calculation of extrema ...
7fd59977 326 gp_Vec OPp (O,Pp);
327 Standard_Real R2 = OPp.SquareMagnitude();
328 if (R2 < Tol * Tol) { return; }
329
330 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
331 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
7c4e9501 332 if (U1 > -ExtPElS_MyEps && U1 < ExtPElS_MyEps) { U1 = 0.; }
c6541a0c
D
333 Standard_Real U2 = U1 + M_PI;
334 if (U1 < 0.) { U1 += 2. * M_PI; }
7fd59977 335 Standard_Real R = sqrt(R2);
336 gp_Vec OO1 = OPp.Divided(R).Multiplied(S.MajorRadius());
337 gp_Vec OO2 = OO1.Multiplied(-1.);
338 gp_Pnt O1 = O.Translated(OO1);
339 gp_Pnt O2 = O.Translated(OO2);
340
341 if(O1.SquareDistance(P) < Tol) { return; }
342 if(O2.SquareDistance(P) < Tol) { return; }
343
5a0fc7ce 344 Standard_Real V1 = OPp.AngleWithRef(gp_Vec(O1,P),OPp.Crossed(OZ));
7c4e9501 345 if (V1 > -ExtPElS_MyEps && V1 < ExtPElS_MyEps) { V1 = 0.; }
5a0fc7ce 346 OPp.Reverse();
347 Standard_Real V2 = OPp.AngleWithRef(gp_Vec(P,O2),OPp.Crossed(OZ));
7c4e9501 348 if (V2 > -ExtPElS_MyEps && V2 < ExtPElS_MyEps) { V2 = 0.; }
349
c6541a0c
D
350 if (V1 < 0.) { V1 += 2. * M_PI; }
351 if (V2 < 0.) { V2 += 2. * M_PI; }
7fd59977 352
353 gp_Pnt Ps;
354 Ps = ElSLib::Value(U1,V1,S);
355 mySqDist[0] = Ps.SquareDistance(P);
356 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
357
c6541a0c 358 Ps = ElSLib::Value(U1,V1+M_PI,S);
7fd59977 359 mySqDist[1] = Ps.SquareDistance(P);
c6541a0c 360 myPoint[1] = Extrema_POnSurf(U1,V1+M_PI,Ps);
7fd59977 361
362 Ps = ElSLib::Value(U2,V2,S);
363 mySqDist[2] = Ps.SquareDistance(P);
364 myPoint[2] = Extrema_POnSurf(U2,V2,Ps);
365
c6541a0c 366 Ps = ElSLib::Value(U2,V2+M_PI,S);
7fd59977 367 mySqDist[3] = Ps.SquareDistance(P);
c6541a0c 368 myPoint[3] = Extrema_POnSurf(U2,V2+M_PI,Ps);
7fd59977 369
370 myNbExt = 4;
371 myDone = Standard_True;
372}
373
374
375Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
376 const gp_Pln& S,
377 const Standard_Real Tol)
378{
379 Perform(P, S, Tol);
380}
381
382void Extrema_ExtPElS::Perform (const gp_Pnt& P,
383 const gp_Pln& S,
384// const Standard_Real Tol)
385 const Standard_Real )
386{
387 myDone = Standard_False;
388 myNbExt = 0;
389
0d969553 390// Projection of point P in plane XOY of the cylinder ...
7fd59977 391 gp_Pnt O = S.Location();
392 gp_Vec OZ (S.Axis().Direction());
393 Standard_Real U, V = gp_Vec(O,P).Dot(OZ);
394 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
395
396 ElSLib::Parameters(S, P, U, V);
397 mySqDist[0] = Pp.SquareDistance(P);
398 myPoint[0] = Extrema_POnSurf(U,V,Pp);
399 myNbExt = 1;
400 myDone = Standard_True;
401}
402
403
404//=============================================================================
405
406Standard_Boolean Extrema_ExtPElS::IsDone () const { return myDone; }
407//=============================================================================
408
409Standard_Integer Extrema_ExtPElS::NbExt () const
410{
9775fa61 411 if (!IsDone()) { throw StdFail_NotDone(); }
7fd59977 412 return myNbExt;
413}
414//=============================================================================
415
416Standard_Real Extrema_ExtPElS::SquareDistance (const Standard_Integer N) const
417{
9775fa61 418 if (!IsDone()) { throw StdFail_NotDone(); }
419 if ((N < 1) || (N > myNbExt)) { throw Standard_OutOfRange(); }
7fd59977 420 return mySqDist[N-1];
421}
422//=============================================================================
423
5d99f2c8 424const Extrema_POnSurf& Extrema_ExtPElS::Point (const Standard_Integer N) const
7fd59977 425{
9775fa61 426 if (!IsDone()) { throw StdFail_NotDone(); }
427 if ((N < 1) || (N > myNbExt)) { throw Standard_OutOfRange(); }
7fd59977 428 return myPoint[N-1];
429}
430//=============================================================================