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