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 | |
12 | Extrema_ExtPElS::Extrema_ExtPElS () { myDone = Standard_False; } |
13 | //============================================================================= |
14 | |
15 | Extrema_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 | /*----------------------------------------------------------------------------- |
23 | Fonction: |
24 | Recherche des 2 distances extremales entre le point P et le cylindre S. |
25 | |
26 | Methode: |
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 | |
39 | void 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 | |
74 | Extrema_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 | /*----------------------------------------------------------------------------- |
81 | Fonction: |
82 | Recherche des 2 distances extremales entre le point P et le cone S. |
83 | |
84 | Methode: |
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 | |
110 | void 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 | |
191 | Extrema_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 | /*----------------------------------------------------------------------------- |
198 | Fonction: |
199 | Recherche des 2 distances extremales entre le point P et la sphere S. |
200 | |
201 | Methode: |
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 | |
219 | void 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 | |
269 | Extrema_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 | /*----------------------------------------------------------------------------- |
276 | Fonction: |
277 | Recherche des 2 distances extremales entre le point P et le tore S. |
278 | |
279 | Methode: |
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 | -----------------------------------------------------------------------------*/ |
294 | void 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 | |
352 | Extrema_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 | |
359 | void 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 | |
383 | Standard_Boolean Extrema_ExtPElS::IsDone () const { return myDone; } |
384 | //============================================================================= |
385 | |
386 | Standard_Integer Extrema_ExtPElS::NbExt () const |
387 | { |
388 | if (!IsDone()) { StdFail_NotDone::Raise(); } |
389 | return myNbExt; |
390 | } |
391 | //============================================================================= |
392 | |
393 | Standard_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 | |
401 | Extrema_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 | //============================================================================= |