Commit | Line | Data |
---|---|---|
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 | 29 | static const Standard_Real ExtPElS_MyEps = Epsilon(2. * M_PI); |
7fd59977 | 30 | //============================================================================= |
31 | ||
32 | Extrema_ExtPElS::Extrema_ExtPElS () { myDone = Standard_False; } | |
33 | //============================================================================= | |
34 | ||
35 | Extrema_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 |
43 | Function: |
44 | Find 2 extreme distances between point P and cylinder S. | |
7fd59977 | 45 | |
0d969553 Y |
46 | Method: |
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 | ||
59 | void 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 | ||
95 | Extrema_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 |
102 | Function: |
103 | Find 2 extreme distances between point P and cone S. | |
7fd59977 | 104 | |
0d969553 Y |
105 | Method: |
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 | ||
131 | void 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 | ||
208 | Extrema_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 |
215 | Function: |
216 | Find 2 extreme distances between point P and sphere S. | |
7fd59977 | 217 | |
0d969553 Y |
218 | Method: |
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 | ||
236 | void 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 | ||
287 | Extrema_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 |
294 | Function: |
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 | -----------------------------------------------------------------------------*/ |
312 | void 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 | ||
375 | Extrema_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 | ||
382 | void 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 | ||
406 | Standard_Boolean Extrema_ExtPElS::IsDone () const { return myDone; } | |
407 | //============================================================================= | |
408 | ||
409 | Standard_Integer Extrema_ExtPElS::NbExt () const | |
410 | { | |
9775fa61 | 411 | if (!IsDone()) { throw StdFail_NotDone(); } |
7fd59977 | 412 | return myNbExt; |
413 | } | |
414 | //============================================================================= | |
415 | ||
416 | Standard_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 | 424 | const 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 | //============================================================================= |