OCC22540 Regression: Exception during building of patch by GeomPlate
[occt.git] / src / Extrema / Extrema_ExtPElS.cxx
CommitLineData
7fd59977 1// modified by MPS (june 96) gestion du cas ou le plan de reference du cone
2// passe par le sommet ( O et M sont alors confondus)
3//
4//
5#include <Extrema_ExtPElS.ixx>
6#include <StdFail_NotDone.hxx>
7#include <Standard_OutOfRange.hxx>
8#include <Standard_NotImplemented.hxx>
9#include <ElSLib.hxx>
10//=============================================================================
11
12Extrema_ExtPElS::Extrema_ExtPElS () { myDone = Standard_False; }
13//=============================================================================
14
15Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
16 const gp_Cylinder& S,
17 const Standard_Real Tol)
18{
19
20 Perform(P, S, Tol);
21}
22/*-----------------------------------------------------------------------------
23Fonction:
24 Recherche des 2 distances extremales entre le point P et le cylindre S.
25
26Methode:
27 Soit Pp la projection de P dans le plan XOY du cylindre;
28 2 cas sont consideres:
29 1- distance(Pp,O) < Tol:
30 Il y a une infinite de solutions; IsDone() = Standard_False.
31 2- distance(Pp,O) > Tol:
32 Soit V = OP.OZ,
33 U1 = angle(OX,OPp) avec 0 < U1 < 2.*PI
34 U2 = U1 + PI avec 0 < U2 < 2.*PI;
35 alors (U1,V) correspond a la distance minimale
36 et (U2,V) correspond a la distance maximale.
37-----------------------------------------------------------------------------*/
38
39void Extrema_ExtPElS::Perform(const gp_Pnt& P,
40 const gp_Cylinder& S,
41 const Standard_Real Tol)
42{
43 myDone = Standard_False;
44 myNbExt = 0;
45
46// Projection du point P dans le plan XOY du cylindre ...
47 gp_Ax3 Pos = S.Position();
48 gp_Pnt O = Pos.Location();
49 gp_Vec OZ (Pos.Direction());
50 Standard_Real V = gp_Vec(O,P).Dot(OZ);
51 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
52
53// Calcul des extrema
54 gp_Vec OPp (O,Pp);
55 if (OPp.Magnitude() < Tol) { return; }
56 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
57 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-PI<U1<PI
58 Standard_Real U2 = U1 + PI;
59 if (U1 < 0.) { U1 += 2. * PI; }
60
61 gp_Pnt Ps;
62 Ps = ElSLib::Value(U1,V,S);
63 mySqDist[0] = Ps.SquareDistance(P);
64 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
65 Ps = ElSLib::Value(U2,V,S);
66 mySqDist[1] = Ps.SquareDistance(P);
67 myPoint[1] = Extrema_POnSurf(U2,V,Ps);
68
69 myNbExt = 2;
70 myDone = Standard_True;
71}
72//=============================================================================
73
74Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
75 const gp_Cone& S,
76 const Standard_Real Tol)
77{
78 Perform(P, S, Tol);
79}
80/*-----------------------------------------------------------------------------
81Fonction:
82 Recherche des 2 distances extremales entre le point P et le cone S.
83
84Methode:
85 Soit M le sommet du cone.
86 2 cas sont consideres:
87 1- distance(P,M) < Tol:
88 Il y a un minimum en M.
89 2- distance(P,M) > Tol:
90 Soit Pp la projection de P dans le plan XOY du cone;
91 2 cas sont consideres:
92 1- distance(Pp,O) < Tol:
93 Il y a une infinite de solutions; IsDone() = Standard_False.
94 2- distance(Pp,O) > Tol:
95 Il existe 2 extrema:
96 Soit Vm = valeur de v pour le point M,
97 Vp = valeur de v pour le point P,
98 U1 = angle(OX,OPp) si Vp > Vm )
99 -angle(OX,OPp) sinon ) avec 0. < U1 < 2*PI,
100 U2 = U1 + PI avec 0. < U2 < 2*PI;
101 On se place dans le plan PpOZ.
102 Soit A l'angle du cone,
103 B = angle(MP,MO) avec 0. < B < PI,
104 L = longueur(MP),
105 V1 = (L * cos(B-A)) + Vm,
106 V2 = (L * cos(B+A)) + Vm;
107 alors (U1,V1) et (U2,V2) correspondent aux distances minimales.
108-----------------------------------------------------------------------------*/
109
110void Extrema_ExtPElS::Perform(const gp_Pnt& P,
111 const gp_Cone& S,
112 const Standard_Real Tol)
113{
114 myDone = Standard_False;
115 myNbExt = 0;
116
117 gp_Pnt M = S.Apex();
118 gp_Ax3 Pos = S.Position();
119 gp_Pnt O = Pos.Location();
120 Standard_Real A = S.SemiAngle();
121 gp_Vec OZ (Pos.Direction());
122 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
123 gp_Vec MP (M,P);
124
125 Standard_Real L2 = MP.SquareMagnitude();
126 Standard_Real Vm = -(S.RefRadius() / Sin(A));
127#ifdef DEB
128 Standard_Real Zm = gp_Vec(O, M).Dot(OZ);
129#else
130 gp_Vec(O, M).Dot(OZ);
131#endif
132
133// Cas ou P est confondu avec S ...
134 if (L2 < Tol * Tol) {
135 mySqDist[0] = L2;
136 myPoint[0] = Extrema_POnSurf(0.,Vm,M);
137 myNbExt = 1;
138 myDone = Standard_True;
139 return;
140 }
141 gp_Vec DirZ;
142 if (M.SquareDistance(O)<Tol * Tol)
143 { DirZ=OZ;
144 if( A<0) DirZ.Multiplied(-1.);
145 }
146 else
147 DirZ=gp_Vec(M,O);
148// Projection de P dans le plan de reference du cone ...
149 Standard_Real Zp = gp_Vec(O, P).Dot(OZ);
150
151 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
152 gp_Vec OPp(O, Pp);
153 if (OPp.SquareMagnitude() < Tol * Tol) return;
154 Standard_Real B, U1, V1, U2, V2;
155 Standard_Boolean Same = DirZ.Dot(MP) >= 0.0;
156 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ); //-PI<U1<PI
157 B = MP.Angle(DirZ);
158 if (!Same) { U1 += PI; }
159 U2 = U1 + PI;
160 if (U1 < 0.) { U1 += 2. * PI; }
161 if (U2 > 2.*PI) { U2 -= 2. * PI; }
162 B = MP.Angle(DirZ);
163 A = Abs(A);
164 Standard_Real L = sqrt(L2);
165 if (!Same) {
166 B = PI-B;
167 V1 = -L*cos(B-A);
168 V2 = -L*cos(B+A);
169 }
170 else {
171 V1 = L * cos(B-A);
172 V2 = L * cos(B+A);
173 }
174 Standard_Real Sense = OZ.Dot(gp_Dir(DirZ));
175 V1 *= Sense; V2 *= Sense;
176 V1 += Vm; V2 += Vm;
177
178 gp_Pnt Ps;
179 Ps = ElSLib::Value(U1,V1,S);
180 mySqDist[0] = Ps.SquareDistance(P);
181 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
182 Ps = ElSLib::Value(U2,V2,S);
183 mySqDist[1] = Ps.SquareDistance(P);
184 myPoint[1] = Extrema_POnSurf(U2,V2,Ps);
185
186 myNbExt = 2;
187 myDone = Standard_True;
188}
189//=============================================================================
190
191Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
192 const gp_Sphere& S,
193 const Standard_Real Tol)
194{
195 Perform(P, S, Tol);
196}
197/*-----------------------------------------------------------------------------
198Fonction:
199 Recherche des 2 distances extremales entre le point P et la sphere S.
200
201Methode:
202 Soit O l'origine de la sphere.
203 2 cas sont consideres:
204 1- distance(P,O) < Tol:
205 Il y a une infinite de solutions; IsDone() = Standard_False
206 2- distance(P,O) > Tol:
207 Soit Pp la projection du point P dans le plan XOY de la sphere;
208 2 cas sont consideres:
209 1- distance(Pp,O) < Tol:
210 Les 2 solutions sont: (0,-PI/2.) et (0.,PI/2.)
211 2- distance(Pp,O) > Tol:
212 Soit U1 = angle(OX,OPp) avec 0. < U1 < 2.*PI,
213 U2 = U1 + PI avec 0. < U2 < 2*PI,
214 V1 = angle(OPp,OP) avec -PI/2. < V1 < PI/2. ,
215 alors (U1, V1) correspond a la distance minimale
216 et (U2,-V1) correspond a la distance maximale.
217-----------------------------------------------------------------------------*/
218
219void Extrema_ExtPElS::Perform(const gp_Pnt& P,
220 const gp_Sphere& S,
221 const Standard_Real Tol)
222{
223 myDone = Standard_False;
224 myNbExt = 0;
225
226 gp_Ax3 Pos = S.Position();
227 gp_Vec OP (Pos.Location(),P);
228
229// Cas ou P est confondu avec O ...
230 if (OP.SquareMagnitude() < Tol * Tol) { return; }
231
232// Projection de P dans le plan XOY de la sphere ...
233 gp_Pnt O = Pos.Location();
234 gp_Vec OZ (Pos.Direction());
235 Standard_Real Zp = OP.Dot(OZ);
236 gp_Pnt Pp = P.Translated(OZ.Multiplied(-Zp));
237
238// Calcul des extrema ...
239 gp_Vec OPp (O,Pp);
240 Standard_Real U1, U2, V;
241 if (OPp.SquareMagnitude() < Tol * Tol) {
242 U1 = 0.;
243 U2 = 0.;
244 if (Zp < 0.) { V = -PI / 2.; }
245 else { V = PI / 2.; }
246 }
247 else {
248 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
249 U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
250 U2 = U1 + PI;
251 if (U1 < 0.) { U1 += 2. * PI; }
252 V = OP.Angle(OPp);
253 if (Zp < 0.) { V = -V; }
254 }
255
256 gp_Pnt Ps;
257 Ps = ElSLib::Value(U1,V,S);
258 mySqDist[0] = Ps.SquareDistance(P);
259 myPoint[0] = Extrema_POnSurf(U1,V,Ps);
260 Ps = ElSLib::Value(U2,-V,S);
261 mySqDist[1] = Ps.SquareDistance(P);
262 myPoint[1] = Extrema_POnSurf(U2,-V,Ps);
263
264 myNbExt = 2;
265 myDone = Standard_True;
266}
267//=============================================================================
268
269Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
270 const gp_Torus& S,
271 const Standard_Real Tol)
272{
273 Perform(P, S, Tol);
274}
275/*-----------------------------------------------------------------------------
276Fonction:
277 Recherche des 2 distances extremales entre le point P et le tore S.
278
279Methode:
280 Soit Pp la projection du point P dans le plan XOY du tore;
281 2 cas sont consideres:
282 1- distance(Pp,O) < Tol:
283 Il y a une infinite de solutions; IsDone() = Standard_False.
284 2- distance(Pp,O) > Tol:
285 On se place dans le plan PpOZ;
286 Soit V1 = angle(OX,OPp) avec 0. < V1 < 2.*PI,
287 V2 = V1 + PI avec 0. < V2 < 2.*PI,
288 O1 et O2 les centres des cercles (O1 sur coord. posit.)
289 U1 = angle(OPp,O1P),
290 U2 = angle(OPp,PO2);
291 alors (U1,V1) correspond a la distance minimale
292 et (U2,V2) correspond a la distance maximale.
293-----------------------------------------------------------------------------*/
294void Extrema_ExtPElS::Perform(const gp_Pnt& P,
295 const gp_Torus& S,
296 const Standard_Real Tol)
297{
298 myDone = Standard_False;
299 myNbExt = 0;
300
301// Projection de P dans le plan XOY ...
302 gp_Ax3 Pos = S.Position();
303 gp_Pnt O = Pos.Location();
304 gp_Vec OZ (Pos.Direction());
305 gp_Pnt Pp = P.Translated(OZ.Multiplied(-(gp_Vec(O,P).Dot(Pos.Direction()))));
306
307// Calcul des extrema ...
308 gp_Vec OPp (O,Pp);
309 Standard_Real R2 = OPp.SquareMagnitude();
310 if (R2 < Tol * Tol) { return; }
311
312 gp_Vec myZ = Pos.XDirection()^Pos.YDirection();
313 Standard_Real U1 = gp_Vec(Pos.XDirection()).AngleWithRef(OPp,myZ);
314 Standard_Real U2 = U1 + PI;
315 if (U1 < 0.) { U1 += 2. * PI; }
316 Standard_Real R = sqrt(R2);
317 gp_Vec OO1 = OPp.Divided(R).Multiplied(S.MajorRadius());
318 gp_Vec OO2 = OO1.Multiplied(-1.);
319 gp_Pnt O1 = O.Translated(OO1);
320 gp_Pnt O2 = O.Translated(OO2);
321
322 if(O1.SquareDistance(P) < Tol) { return; }
323 if(O2.SquareDistance(P) < Tol) { return; }
324
325 Standard_Real V1 = OO1.AngleWithRef(gp_Vec(O1,P),OO1.Crossed(OZ));
326 Standard_Real V2 = OO2.AngleWithRef(gp_Vec(P,O2),OO2.Crossed(OZ));
327 if (V1 < 0.) { V1 += 2. * PI; }
328 if (V2 < 0.) { V2 += 2. * PI; }
329
330 gp_Pnt Ps;
331 Ps = ElSLib::Value(U1,V1,S);
332 mySqDist[0] = Ps.SquareDistance(P);
333 myPoint[0] = Extrema_POnSurf(U1,V1,Ps);
334
335 Ps = ElSLib::Value(U1,V1+PI,S);
336 mySqDist[1] = Ps.SquareDistance(P);
337 myPoint[1] = Extrema_POnSurf(U1,V1+PI,Ps);
338
339 Ps = ElSLib::Value(U2,V2,S);
340 mySqDist[2] = Ps.SquareDistance(P);
341 myPoint[2] = Extrema_POnSurf(U2,V2,Ps);
342
343 Ps = ElSLib::Value(U2,V2+PI,S);
344 mySqDist[3] = Ps.SquareDistance(P);
345 myPoint[3] = Extrema_POnSurf(U2,V2+PI,Ps);
346
347 myNbExt = 4;
348 myDone = Standard_True;
349}
350
351
352Extrema_ExtPElS::Extrema_ExtPElS (const gp_Pnt& P,
353 const gp_Pln& S,
354 const Standard_Real Tol)
355{
356 Perform(P, S, Tol);
357}
358
359void Extrema_ExtPElS::Perform (const gp_Pnt& P,
360 const gp_Pln& S,
361// const Standard_Real Tol)
362 const Standard_Real )
363{
364 myDone = Standard_False;
365 myNbExt = 0;
366
367// Projection du point P dans le plan XOY du cylindre ...
368 gp_Pnt O = S.Location();
369 gp_Vec OZ (S.Axis().Direction());
370 Standard_Real U, V = gp_Vec(O,P).Dot(OZ);
371 gp_Pnt Pp = P.Translated(OZ.Multiplied(-V));
372
373 ElSLib::Parameters(S, P, U, V);
374 mySqDist[0] = Pp.SquareDistance(P);
375 myPoint[0] = Extrema_POnSurf(U,V,Pp);
376 myNbExt = 1;
377 myDone = Standard_True;
378}
379
380
381//=============================================================================
382
383Standard_Boolean Extrema_ExtPElS::IsDone () const { return myDone; }
384//=============================================================================
385
386Standard_Integer Extrema_ExtPElS::NbExt () const
387{
388 if (!IsDone()) { StdFail_NotDone::Raise(); }
389 return myNbExt;
390}
391//=============================================================================
392
393Standard_Real Extrema_ExtPElS::SquareDistance (const Standard_Integer N) const
394{
395 if (!IsDone()) { StdFail_NotDone::Raise(); }
396 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
397 return mySqDist[N-1];
398}
399//=============================================================================
400
401Extrema_POnSurf Extrema_ExtPElS::Point (const Standard_Integer N) const
402{
403 if (!IsDone()) { StdFail_NotDone::Raise(); }
404 if ((N < 1) || (N > myNbExt)) { Standard_OutOfRange::Raise(); }
405 return myPoint[N-1];
406}
407//=============================================================================