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