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. |
7fd59977 |
14 | |
15 | // Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 |
16 | |
42cf5bc1 |
17 | #include <ElCLib.hxx> |
18 | #include <ElSLib.hxx> |
7fd59977 |
19 | #include <Extrema_ExtElC.hxx> |
42cf5bc1 |
20 | #include <Extrema_ExtElCS.hxx> |
21 | #include <Extrema_ExtPElC.hxx> |
22 | #include <Extrema_ExtPElS.hxx> |
7fd59977 |
23 | #include <Extrema_POnCurv.hxx> |
42cf5bc1 |
24 | #include <Extrema_POnSurf.hxx> |
25 | #include <gp_Circ.hxx> |
26 | #include <gp_Cone.hxx> |
27 | #include <gp_Cylinder.hxx> |
28 | #include <gp_Hypr.hxx> |
29 | #include <gp_Lin.hxx> |
30 | #include <gp_Pln.hxx> |
31 | #include <gp_Sphere.hxx> |
32 | #include <gp_Torus.hxx> |
7fd59977 |
33 | #include <gp_Vec.hxx> |
f34cd0d1 |
34 | #include <IntAna_IntConicQuad.hxx> |
42cf5bc1 |
35 | #include <IntAna_Quadric.hxx> |
03cca6f7 |
36 | #include <IntAna_QuadQuadGeo.hxx> |
42cf5bc1 |
37 | #include <Precision.hxx> |
38 | #include <Standard_NotImplemented.hxx> |
39 | #include <Standard_OutOfRange.hxx> |
42cf5bc1 |
40 | #include <StdFail_NotDone.hxx> |
03cca6f7 |
41 | #include <TColStd_ListOfInteger.hxx> |
7fd59977 |
42 | |
43 | Extrema_ExtElCS::Extrema_ExtElCS() |
44 | { |
45 | myDone = Standard_False; |
46 | myIsPar = Standard_False; |
638ad7f3 |
47 | myNbExt = 0; |
7fd59977 |
48 | } |
49 | |
50 | |
51 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, |
52 | const gp_Pln& S) |
53 | { |
54 | Perform(C, S); |
55 | } |
56 | |
57 | |
58 | |
59 | void Extrema_ExtElCS::Perform(const gp_Lin& C, |
60 | const gp_Pln& S) |
61 | { |
62 | myDone = Standard_True; |
63 | myIsPar = Standard_False; |
638ad7f3 |
64 | myNbExt = 0; |
7fd59977 |
65 | |
638ad7f3 |
66 | if (C.Direction().IsNormal(S.Axis().Direction(), |
67 | Precision::Angular())) |
68 | { |
7fd59977 |
69 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
70 | mySqDist->SetValue(1, S.SquareDistance(C)); |
71 | myIsPar = Standard_True; |
638ad7f3 |
72 | myNbExt = 1; |
7fd59977 |
73 | } |
7fd59977 |
74 | } |
75 | |
76 | |
77 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, |
78 | const gp_Cylinder& S) |
79 | { |
80 | Perform(C, S); |
81 | } |
82 | |
83 | |
84 | |
85 | void Extrema_ExtElCS::Perform(const gp_Lin& C, |
db914841 |
86 | const gp_Cylinder& S) |
7fd59977 |
87 | { |
88 | myDone = Standard_False; |
89 | myNbExt = 0; |
90 | myIsPar = Standard_False; |
91 | |
92 | gp_Ax3 Pos = S.Position(); |
638ad7f3 |
93 | |
94 | Standard_Boolean isParallel = Standard_False; |
f34cd0d1 |
95 | |
7fd59977 |
96 | Standard_Real radius = S.Radius(); |
97 | Extrema_ExtElC Extrem(gp_Lin(Pos.Axis()), C, Precision::Angular()); |
638ad7f3 |
98 | if (Extrem.IsParallel()) |
99 | { |
100 | isParallel = Standard_True; |
7fd59977 |
101 | } |
638ad7f3 |
102 | else |
103 | { |
db914841 |
104 | Standard_Integer i, aStartIdx = 0; |
105 | |
f34cd0d1 |
106 | Extrema_POnCurv myPOnC1, myPOnC2; |
107 | Extrem.Points(1, myPOnC1, myPOnC2); |
108 | gp_Pnt PonAxis = myPOnC1.Value(); |
109 | gp_Pnt PC = myPOnC2.Value(); |
110 | |
f34cd0d1 |
111 | // line intersects the cylinder |
db914841 |
112 | if (radius - PonAxis.Distance(PC) > Precision::PConfusion()) |
f34cd0d1 |
113 | { |
114 | IntAna_Quadric theQuadric(S); |
115 | IntAna_IntConicQuad Inters(C, theQuadric); |
638ad7f3 |
116 | if (Inters.IsDone() && Inters.IsInQuadric()) |
117 | { |
118 | isParallel = Standard_True; |
119 | } |
120 | else if (Inters.IsDone()) |
f34cd0d1 |
121 | { |
122 | myNbExt = Inters.NbPoints(); |
db914841 |
123 | aStartIdx = myNbExt; |
f34cd0d1 |
124 | if (myNbExt > 0) |
125 | { |
db914841 |
126 | // Not more than 2 additional points from perpendiculars. |
127 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2); |
128 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2); |
129 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2); |
f34cd0d1 |
130 | Standard_Real u, v, w; |
131 | for (i = 1; i <= myNbExt; i++) |
132 | { |
133 | mySqDist->SetValue(i, 0.); |
134 | gp_Pnt P_int = Inters.Point(i); |
135 | w = Inters.ParamOnConic(i); |
136 | Extrema_POnCurv PonC(w, P_int); |
137 | myPoint1->SetValue(i, PonC); |
138 | ElSLib::CylinderParameters(Pos, radius, P_int, u, v); |
139 | Extrema_POnSurf PonS(u, v, P_int); |
140 | myPoint2->SetValue(i, PonS); |
141 | } |
142 | } |
7fd59977 |
143 | } |
7fd59977 |
144 | } |
638ad7f3 |
145 | else |
146 | { |
147 | // line is tangent or outside of the cylinder |
148 | Extrema_ExtPElS ExPS(PC, S, Precision::Confusion()); |
db914841 |
149 | if (ExPS.IsDone()) |
150 | { |
151 | if (aStartIdx == 0) |
152 | { |
153 | myNbExt = ExPS.NbExt(); |
154 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt); |
155 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); |
156 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); |
157 | } |
158 | else |
159 | myNbExt += ExPS.NbExt(); |
160 | |
638ad7f3 |
161 | for (i = aStartIdx + 1; i <= myNbExt; i++) |
162 | { |
db914841 |
163 | myPoint1->SetValue(i, myPOnC2); |
164 | myPoint2->SetValue(i, ExPS.Point(i - aStartIdx)); |
638ad7f3 |
165 | mySqDist->SetValue(i, (myPOnC2.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value())); |
db914841 |
166 | } |
167 | } |
638ad7f3 |
168 | } |
169 | |
f34cd0d1 |
170 | myDone = Standard_True; |
7fd59977 |
171 | } |
172 | |
638ad7f3 |
173 | if (isParallel) |
174 | { |
175 | // Line direction is similar to cylinder axis of rotation. |
176 | // The case is possible when either extrema returned parallel status |
177 | // or Intersection tool returned infinite number of solutions. |
178 | // This is possible due to Intersection algorithm uses more precise |
179 | // characteristics to consider given geometries parallel. |
180 | // In the latter case there may be several extremas, thus we look for |
181 | // the one with the lowest distance and use it as a final solution. |
182 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
183 | Standard_Real aDist = Extrem.SquareDistance(1); |
184 | const Standard_Integer aNbExt = Extrem.NbExt(); |
185 | for (Standard_Integer i = 2; i <= aNbExt; i++) |
186 | { |
187 | const Standard_Real aD = Extrem.SquareDistance(i); |
188 | if (aD < aDist) |
189 | { |
190 | aDist = aD; |
191 | } |
192 | } |
193 | |
194 | aDist = sqrt(aDist) - radius; |
195 | mySqDist->SetValue(1, aDist * aDist); |
196 | myDone = Standard_True; |
197 | myIsPar = Standard_True; |
198 | myNbExt = 1; |
199 | } |
7fd59977 |
200 | } |
201 | |
202 | |
203 | |
204 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, |
205 | const gp_Cone& S) |
9775fa61 |
206 | { Perform(C, S);} |
7fd59977 |
207 | |
208 | |
209 | |
210 | //void Extrema_ExtElCS::Perform(const gp_Lin& C, |
211 | // const gp_Cone& S) |
212 | void Extrema_ExtElCS::Perform(const gp_Lin& , |
213 | const gp_Cone& ) |
214 | { |
9775fa61 |
215 | throw Standard_NotImplemented(); |
7fd59977 |
216 | |
217 | } |
218 | |
219 | |
220 | |
221 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, |
222 | const gp_Sphere& S) |
223 | { |
224 | Perform(C, S); |
225 | } |
226 | |
227 | |
228 | |
229 | void Extrema_ExtElCS::Perform(const gp_Lin& C, |
db914841 |
230 | const gp_Sphere& S) |
7fd59977 |
231 | { |
db914841 |
232 | // In case of intersection - return four points: |
233 | // 2 intersection points and 2 perpendicular. |
234 | // No intersection - only min and max. |
235 | |
7fd59977 |
236 | myDone = Standard_False; |
237 | myNbExt = 0; |
238 | myIsPar = Standard_False; |
db914841 |
239 | Standard_Integer aStartIdx = 0; |
7fd59977 |
240 | |
db914841 |
241 | gp_Pnt aCenter = S.Location(); |
7fd59977 |
242 | |
db914841 |
243 | Extrema_ExtPElC Extrem(aCenter, C, Precision::Angular(), RealFirst(), RealLast()); |
7fd59977 |
244 | |
245 | Standard_Integer i; |
db914841 |
246 | if (Extrem.IsDone() && |
247 | Extrem.NbExt() > 0) |
248 | { |
7fd59977 |
249 | Extrema_POnCurv myPOnC1 = Extrem.Point(1); |
db914841 |
250 | if (myPOnC1.Value().Distance(aCenter) <= S.Radius()) |
251 | { |
252 | IntAna_IntConicQuad aLinSphere(C, S); |
253 | if (aLinSphere.IsDone()) |
254 | { |
255 | myNbExt = aLinSphere.NbPoints(); |
256 | aStartIdx = myNbExt; |
257 | // Not more than 2 additional points from perpendiculars. |
258 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt + 2); |
259 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt + 2); |
260 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt + 2); |
261 | |
262 | for (i = 1; i <= myNbExt; i++) |
263 | { |
264 | Extrema_POnCurv aCPnt(aLinSphere.ParamOnConic(i), aLinSphere.Point(i)); |
265 | |
266 | Standard_Real u,v; |
267 | ElSLib::Parameters(S, aLinSphere.Point(i), u, v); |
268 | Extrema_POnSurf aSPnt(u, v, aLinSphere.Point(i)); |
269 | |
270 | myPoint1->SetValue(i, aCPnt); |
271 | myPoint2->SetValue(i, aSPnt); |
272 | mySqDist->SetValue(i,(aCPnt.Value()).SquareDistance(aSPnt.Value())); |
273 | } |
274 | } |
275 | } |
276 | |
7fd59977 |
277 | Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion()); |
db914841 |
278 | if (ExPS.IsDone()) |
279 | { |
280 | if (aStartIdx == 0) |
281 | { |
282 | myNbExt = ExPS.NbExt(); |
283 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt); |
284 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); |
285 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); |
286 | } |
287 | else |
288 | myNbExt += ExPS.NbExt(); |
289 | |
290 | for (i = aStartIdx + 1; i <= myNbExt; i++) |
291 | { |
292 | myPoint1->SetValue(i, myPOnC1); |
293 | myPoint2->SetValue(i, ExPS.Point(i - aStartIdx)); |
294 | mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i - aStartIdx).Value())); |
7fd59977 |
295 | } |
296 | } |
297 | } |
db914841 |
298 | myDone = Standard_True; |
7fd59977 |
299 | } |
300 | |
301 | |
302 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C, |
303 | const gp_Torus& S) |
9775fa61 |
304 | { Perform(C, S);} |
7fd59977 |
305 | |
306 | |
307 | |
308 | //void Extrema_ExtElCS::Perform(const gp_Lin& C, |
309 | // const gp_Torus& S) |
310 | void Extrema_ExtElCS::Perform(const gp_Lin& , |
311 | const gp_Torus& ) |
312 | { |
9775fa61 |
313 | throw Standard_NotImplemented(); |
7fd59977 |
314 | |
315 | } |
316 | |
317 | |
318 | // Circle-? |
319 | |
320 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, |
321 | const gp_Pln& S) |
322 | { |
323 | Perform(C, S); |
324 | } |
325 | |
326 | |
327 | |
9dfbbfe6 |
328 | void Extrema_ExtElCS::Perform(const gp_Circ& C, |
329 | const gp_Pln& S) |
7fd59977 |
330 | { |
9dfbbfe6 |
331 | myDone = Standard_True; |
332 | myIsPar = Standard_False; |
638ad7f3 |
333 | myNbExt = 0; |
9dfbbfe6 |
334 | |
335 | gp_Ax2 Pos = C.Position(); |
336 | gp_Dir NCirc = Pos.Direction(); |
337 | gp_Dir NPln = S.Axis().Direction(); |
338 | |
638ad7f3 |
339 | Standard_Boolean isParallel = Standard_False; |
9dfbbfe6 |
340 | |
638ad7f3 |
341 | if (NCirc.IsParallel(NPln, Precision::Angular())) { |
342 | isParallel = Standard_True; |
9dfbbfe6 |
343 | } |
344 | else { |
345 | |
346 | gp_Dir ExtLine = NCirc ^ NPln; |
347 | ExtLine = ExtLine ^ NCirc; |
348 | // |
349 | gp_Dir XDir = Pos.XDirection(); |
350 | Standard_Real T[2]; |
351 | T[0] = XDir.AngleWithRef(ExtLine, NCirc); |
352 | if(T[0] < 0.) |
353 | { |
354 | //Put in period |
355 | T[0] += M_PI; |
356 | } |
357 | T[1] = T[0] + M_PI; |
358 | // |
359 | myNbExt = 2; |
360 | //Check intersection |
361 | IntAna_IntConicQuad anInter(C, S, |
362 | Precision::Angular(), |
363 | Precision::Confusion()); |
638ad7f3 |
364 | |
365 | if (anInter.IsDone() && anInter.IsInQuadric()) |
366 | { |
367 | isParallel = Standard_True; |
368 | } |
369 | else if (anInter.IsDone()) |
9dfbbfe6 |
370 | { |
371 | if(anInter.NbPoints() > 1) |
372 | { |
373 | myNbExt += anInter.NbPoints(); |
374 | } |
375 | } |
376 | |
638ad7f3 |
377 | if (!isParallel) |
9dfbbfe6 |
378 | { |
638ad7f3 |
379 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); |
380 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt); |
381 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); |
382 | |
383 | Standard_Integer i; |
384 | gp_Pnt PC, PP; |
385 | Standard_Real U, V; |
386 | Extrema_POnCurv POnC; |
387 | Extrema_POnSurf POnS; |
388 | for (i = 0; i < 2; ++i) |
9dfbbfe6 |
389 | { |
638ad7f3 |
390 | PC = ElCLib::CircleValue(T[i], C.Position(), C.Radius()); |
391 | POnC.SetValues(T[i], PC); |
392 | myPoint1->SetValue(i + 1, POnC); |
9dfbbfe6 |
393 | ElSLib::PlaneParameters(S.Position(), PC, U, V); |
394 | PP = ElSLib::PlaneValue(U, V, S.Position()); |
395 | POnS.SetParameters(U, V, PP); |
638ad7f3 |
396 | myPoint2->SetValue(i + 1, POnS); |
397 | mySqDist->SetValue(i + 1, PC.SquareDistance(PP)); |
398 | } |
399 | // |
400 | if (myNbExt > 2) |
401 | { |
402 | //Add intersection points |
403 | for (i = 1; i <= anInter.NbPoints(); ++i) |
404 | { |
405 | Standard_Real t = anInter.ParamOnConic(i); |
406 | PC = ElCLib::CircleValue(t, C.Position(), C.Radius()); |
407 | POnC.SetValues(t, PC); |
408 | myPoint1->SetValue(i + 2, POnC); |
409 | ElSLib::PlaneParameters(S.Position(), PC, U, V); |
410 | PP = ElSLib::PlaneValue(U, V, S.Position()); |
411 | POnS.SetParameters(U, V, PP); |
412 | myPoint2->SetValue(i + 2, POnS); |
413 | mySqDist->SetValue(i + 2, PC.SquareDistance(PP)); |
414 | } |
9dfbbfe6 |
415 | } |
416 | } |
417 | } |
638ad7f3 |
418 | |
419 | if (isParallel) |
420 | { |
421 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
422 | mySqDist->SetValue(1, S.SquareDistance(C.Location())); |
423 | myIsPar = Standard_True; |
424 | myNbExt = 1; |
425 | } |
7fd59977 |
426 | } |
427 | |
7fd59977 |
428 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, |
429 | const gp_Cylinder& S) |
430 | { |
431 | Perform(C, S); |
432 | } |
433 | |
434 | |
435 | |
436 | // Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 Begin |
437 | // Implementation of the method. |
438 | void Extrema_ExtElCS::Perform(const gp_Circ& C, |
439 | const gp_Cylinder& S) |
440 | { |
441 | myDone = Standard_False; |
442 | myIsPar = Standard_False; |
443 | myNbExt = 0; |
444 | |
445 | // Get an axis line of the cylinder. |
446 | gp_Lin anAxis(S.Axis()); |
447 | |
448 | // Compute extrema between the circle and the line. |
449 | Extrema_ExtElC anExtC(anAxis, C, 0.); |
450 | |
638ad7f3 |
451 | if (!anExtC.IsDone()) |
452 | return; |
7fd59977 |
453 | |
638ad7f3 |
454 | Standard_Boolean isParallel = Standard_False; |
455 | |
456 | if (anExtC.IsParallel()) { |
457 | isParallel = Standard_True; |
458 | } else { |
459 | Standard_Integer aNbExt = anExtC.NbExt(); |
460 | Standard_Integer i; |
461 | Standard_Integer aCurI = 1; |
462 | Standard_Real aTolConf = Precision::Confusion(); |
463 | Standard_Real aCylRad = S.Radius(); |
464 | |
465 | // Check whether two objects have intersection points |
466 | IntAna_Quadric aCylQuad(S); |
467 | IntAna_IntConicQuad aCircCylInter(C, aCylQuad); |
468 | Standard_Integer aNbInter = 0; |
469 | if (aCircCylInter.IsDone() && aCircCylInter.IsInQuadric()) |
470 | { |
471 | isParallel = Standard_True; |
472 | } |
473 | else if (aCircCylInter.IsDone()) |
474 | { |
475 | aNbInter = aCircCylInter.NbPoints(); |
476 | } |
19875353 |
477 | |
638ad7f3 |
478 | if (!isParallel) |
479 | { |
7fd59977 |
480 | // Compute the extremas. |
638ad7f3 |
481 | myNbExt = 2 * aNbExt + aNbInter; |
482 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt); |
7fd59977 |
483 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); |
484 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); |
485 | |
486 | for (i = 1; i <= aNbExt; i++) { |
19875353 |
487 | Extrema_POnCurv aPOnAxis; |
488 | Extrema_POnCurv aPOnCirc; |
489 | Standard_Real aSqDist = anExtC.SquareDistance(i); |
638ad7f3 |
490 | Standard_Real aDist = sqrt(aSqDist); |
19875353 |
491 | |
492 | anExtC.Points(i, aPOnAxis, aPOnCirc); |
493 | |
494 | if (aSqDist <= (aTolConf * aTolConf)) { |
495 | myNbExt -= 2; |
496 | continue; |
497 | } |
498 | |
499 | gp_Dir aDir(aPOnAxis.Value().XYZ().Subtracted(aPOnCirc.Value().XYZ())); |
638ad7f3 |
500 | Standard_Real aShift[2] = {aDist + aCylRad, aDist - aCylRad}; |
19875353 |
501 | Standard_Integer j; |
7fd59977 |
502 | |
19875353 |
503 | for (j = 0; j < 2; j++) { |
504 | gp_Vec aVec(aDir); |
505 | gp_Pnt aPntOnCyl; |
7fd59977 |
506 | |
19875353 |
507 | aVec.Multiply(aShift[j]); |
508 | aPntOnCyl = aPOnCirc.Value().Translated(aVec); |
7fd59977 |
509 | |
19875353 |
510 | Standard_Real aU; |
511 | Standard_Real aV; |
7fd59977 |
512 | |
19875353 |
513 | ElSLib::Parameters(S, aPntOnCyl, aU, aV); |
7fd59977 |
514 | |
19875353 |
515 | Extrema_POnSurf aPOnSurf(aU, aV, aPntOnCyl); |
7fd59977 |
516 | |
19875353 |
517 | myPoint1->SetValue(aCurI, aPOnCirc); |
518 | myPoint2->SetValue(aCurI, aPOnSurf); |
519 | mySqDist->SetValue(aCurI++, aShift[j] * aShift[j]); |
520 | } |
521 | } |
522 | |
523 | // Adding intersection points to the list of extremas |
524 | for (i=1; i<=aNbInter; i++) |
525 | { |
526 | Standard_Real aU; |
527 | Standard_Real aV; |
7fd59977 |
528 | |
19875353 |
529 | gp_Pnt aInterPnt = aCircCylInter.Point(i); |
7fd59977 |
530 | |
19875353 |
531 | aU = ElCLib::Parameter(C, aInterPnt); |
532 | Extrema_POnCurv aPOnCirc(aU, aInterPnt); |
7fd59977 |
533 | |
19875353 |
534 | ElSLib::Parameters(S, aInterPnt, aU, aV); |
535 | Extrema_POnSurf aPOnCyl(aU, aV, aInterPnt); |
536 | myPoint1->SetValue(aCurI, aPOnCirc); |
537 | myPoint2->SetValue(aCurI, aPOnCyl); |
538 | mySqDist->SetValue(aCurI++, 0.0); |
7fd59977 |
539 | } |
540 | } |
638ad7f3 |
541 | } |
7fd59977 |
542 | |
638ad7f3 |
543 | myDone = Standard_True; |
544 | |
545 | if (isParallel) |
546 | { |
547 | // The case is possible when either extrema returned parallel status |
548 | // or Intersection tool returned infinite number of solutions. |
549 | // This is possible due to Intersection algorithm uses more precise |
550 | // characteristics to consider given geometries parallel. |
551 | // In the latter case there may be several extremas, thus we look for |
552 | // the one with the lowest distance and use it as a final solution. |
553 | |
554 | myIsPar = Standard_True; |
555 | myNbExt = 1; |
556 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
557 | Standard_Real aDist = anExtC.SquareDistance(1); |
558 | |
559 | const Standard_Integer aNbExt = anExtC.NbExt(); |
560 | for (Standard_Integer i = 2; i <= aNbExt; i++) |
561 | { |
562 | const Standard_Real aD = anExtC.SquareDistance(i); |
563 | if (aD < aDist) |
564 | { |
565 | aDist = aD; |
566 | } |
567 | } |
568 | |
569 | aDist = sqrt(aDist) - S.Radius(); |
570 | mySqDist->SetValue(1, aDist * aDist); |
7fd59977 |
571 | } |
572 | } |
573 | // Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 End |
574 | |
575 | |
576 | |
577 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, |
578 | const gp_Cone& S) |
9775fa61 |
579 | { Perform(C, S);} |
7fd59977 |
580 | |
581 | |
582 | |
583 | //void Extrema_ExtElCS::Perform(const gp_Circ& C, |
584 | // const gp_Cone& S) |
585 | void Extrema_ExtElCS::Perform(const gp_Circ& , |
586 | const gp_Cone& ) |
587 | { |
9775fa61 |
588 | throw Standard_NotImplemented(); |
7fd59977 |
589 | |
590 | } |
591 | |
592 | |
593 | |
03cca6f7 |
594 | //======================================================================= |
595 | //function : Extrema_ExtElCS |
596 | //purpose : Circle/Sphere |
597 | //======================================================================= |
7fd59977 |
598 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, |
03cca6f7 |
599 | const gp_Sphere& S) |
600 | { |
601 | Perform(C, S); |
602 | } |
603 | |
604 | //======================================================================= |
605 | //function : Perform |
606 | //purpose : Circle/Sphere |
607 | //======================================================================= |
608 | void Extrema_ExtElCS::Perform(const gp_Circ& C, |
609 | const gp_Sphere& S) |
610 | { |
611 | myDone = Standard_False; |
638ad7f3 |
612 | myIsPar = Standard_False; |
613 | myNbExt = 0; |
03cca6f7 |
614 | |
615 | if (gp_Lin(C.Axis()).SquareDistance(S.Location()) < Precision::SquareConfusion()) |
616 | { |
617 | // Circle and sphere are parallel |
618 | myIsPar = Standard_True; |
619 | myDone = Standard_True; |
638ad7f3 |
620 | myNbExt = 1; |
7fd59977 |
621 | |
03cca6f7 |
622 | // Compute distance from circle to the sphere |
623 | Standard_Real aSqDistLoc = C.Location().SquareDistance(S.Location()); |
624 | Standard_Real aSqDist = aSqDistLoc + C.Radius() * C.Radius(); |
625 | Standard_Real aDist = sqrt(aSqDist) - S.Radius(); |
626 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
627 | mySqDist->SetValue(1, aDist * aDist); |
628 | return; |
629 | } |
7fd59977 |
630 | |
03cca6f7 |
631 | // Intersect sphere with circle's plane |
632 | gp_Pln CPln(C.Location(), C.Axis().Direction()); |
633 | IntAna_QuadQuadGeo anInter(CPln, S); |
634 | if (!anInter.IsDone()) |
635 | // not done |
636 | return; |
7fd59977 |
637 | |
03cca6f7 |
638 | if (anInter.TypeInter() != IntAna_Circle) |
639 | { |
640 | // Intersection is empty or just a point. |
641 | // The parallel case has already been considered, |
642 | // thus, here we have to find only one minimal solution |
643 | myNbExt = 1; |
644 | myDone = Standard_True; |
645 | |
646 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
647 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1); |
648 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1); |
649 | |
650 | // Compute parameter on circle |
651 | const Standard_Real aT = ElCLib::Parameter(C, S.Location()); |
652 | // Compute point on circle |
653 | gp_Pnt aPOnC = ElCLib::Value(aT, C); |
654 | |
655 | // Compute parameters on sphere |
656 | Standard_Real aU, aV; |
657 | ElSLib::Parameters(S, aPOnC, aU, aV); |
658 | // Compute point on sphere |
659 | gp_Pnt aPOnS = ElSLib::Value(aU, aV, S); |
660 | |
661 | // Save solution |
662 | myPoint1->SetValue(1, Extrema_POnCurv(aT, aPOnC)); |
663 | myPoint2->SetValue(1, Extrema_POnSurf(aU, aV, aPOnS)); |
664 | mySqDist->SetValue(1, aPOnC.SquareDistance(aPOnS)); |
665 | return; |
666 | } |
667 | |
668 | // Here, the intersection is a circle |
669 | |
670 | // Intersection circle |
671 | gp_Circ aCInt = anInter.Circle(1); |
672 | |
673 | // Perform intersection of the input circle with the intersection circle |
674 | Extrema_ExtElC anExtC(C, aCInt); |
675 | Standard_Boolean isExtremaCircCircValid = anExtC.IsDone() // Check if intersection is done |
676 | && !anExtC.IsParallel() // Parallel case has already been considered |
677 | && anExtC.NbExt() > 0; // Check that some solutions have been found |
678 | if (!isExtremaCircCircValid) |
679 | // not done |
680 | return; |
681 | |
682 | myDone = Standard_True; |
683 | |
684 | // Few solutions |
685 | Standard_Real aNbExt = anExtC.NbExt(); |
686 | // Find the minimal distance |
687 | Standard_Real aMinSqDist = ::RealLast(); |
688 | for (Standard_Integer i = 1; i <= aNbExt; ++i) |
689 | { |
690 | Standard_Real aSqDist = anExtC.SquareDistance(i); |
691 | if (aSqDist < aMinSqDist) |
692 | aMinSqDist = aSqDist; |
693 | } |
7fd59977 |
694 | |
03cca6f7 |
695 | // Collect all solutions close to the minimal one |
696 | TColStd_ListOfInteger aSols; |
697 | for (Standard_Integer i = 1; i <= aNbExt; ++i) |
698 | { |
699 | Standard_Real aDiff = anExtC.SquareDistance(i) - aMinSqDist; |
700 | if (aDiff < Precision::SquareConfusion()) |
701 | aSols.Append(i); |
702 | } |
703 | |
704 | // Save all minimal solutions |
705 | myNbExt = aSols.Extent(); |
706 | |
707 | mySqDist = new TColStd_HArray1OfReal(1, myNbExt); |
708 | myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt); |
709 | myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt); |
710 | |
711 | TColStd_ListIteratorOfListOfInteger it(aSols); |
712 | for (Standard_Integer iSol = 1; it.More(); it.Next(), ++iSol) |
713 | { |
714 | Extrema_POnCurv P1, P2; |
715 | anExtC.Points(it.Value(), P1, P2); |
716 | |
717 | // Compute parameters on sphere |
718 | Standard_Real aU, aV; |
719 | ElSLib::Parameters(S, P1.Value(), aU, aV); |
720 | // Compute point on sphere |
721 | gp_Pnt aPOnS = ElSLib::Value(aU, aV, S); |
722 | |
723 | // Save solution |
724 | myPoint1->SetValue(iSol, P1); |
725 | myPoint2->SetValue(iSol, Extrema_POnSurf(aU, aV, aPOnS)); |
726 | mySqDist->SetValue(iSol, P1.Value().SquareDistance(aPOnS)); |
727 | } |
7fd59977 |
728 | } |
729 | |
730 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C, |
731 | const gp_Torus& S) |
9775fa61 |
732 | { Perform(C, S);} |
7fd59977 |
733 | |
734 | |
735 | |
736 | //void Extrema_ExtElCS::Perform(const gp_Circ& C, |
737 | // const gp_Torus& S) |
738 | void Extrema_ExtElCS::Perform(const gp_Circ& , |
739 | const gp_Torus& ) |
740 | { |
9775fa61 |
741 | throw Standard_NotImplemented(); |
7fd59977 |
742 | |
743 | } |
744 | |
745 | Extrema_ExtElCS::Extrema_ExtElCS(const gp_Hypr& C, |
746 | const gp_Pln& S) |
747 | { |
748 | Perform(C, S); |
749 | } |
750 | |
751 | |
752 | |
753 | void Extrema_ExtElCS::Perform(const gp_Hypr& C, |
754 | const gp_Pln& S) |
755 | { |
756 | myDone = Standard_True; |
757 | myIsPar = Standard_False; |
638ad7f3 |
758 | myNbExt = 0; |
7fd59977 |
759 | |
760 | gp_Ax2 Pos = C.Position(); |
761 | gp_Dir NHypr = Pos.Direction(); |
762 | gp_Dir NPln = S.Axis().Direction(); |
763 | |
764 | if (NHypr.IsParallel(NPln, Precision::Angular())) { |
765 | |
766 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
767 | mySqDist->SetValue(1, S.SquareDistance(C.Location())); |
768 | myIsPar = Standard_True; |
638ad7f3 |
769 | myNbExt = 1; |
7fd59977 |
770 | } |
771 | else { |
772 | |
773 | gp_Dir XDir = Pos.XDirection(); |
774 | gp_Dir YDir = Pos.YDirection(); |
775 | |
776 | Standard_Real A = C.MinorRadius()*(NPln.Dot(YDir)); |
777 | Standard_Real B = C.MajorRadius()*(NPln.Dot(XDir)); |
778 | |
779 | if(Abs(B) > Abs(A)) { |
780 | Standard_Real T = -0.5 * Log((A+B)/(B-A)); |
781 | gp_Pnt Ph = ElCLib::HyperbolaValue(T, Pos, C.MajorRadius(), C.MinorRadius()); |
782 | Extrema_POnCurv PC(T, Ph); |
783 | myPoint1 = new Extrema_HArray1OfPOnCurv(1,1); |
784 | myPoint1->SetValue(1, PC); |
785 | |
786 | mySqDist = new TColStd_HArray1OfReal(1, 1); |
787 | mySqDist->SetValue(1, S.SquareDistance(Ph)); |
788 | |
789 | Standard_Real U, V; |
790 | ElSLib::PlaneParameters(S.Position(), Ph, U, V); |
791 | gp_Pnt Pp = ElSLib::PlaneValue(U, V, S.Position()); |
792 | Extrema_POnSurf PS(U, V, Pp); |
793 | myPoint2 = new Extrema_HArray1OfPOnSurf(1,1); |
794 | myPoint2->SetValue(1, PS); |
795 | |
796 | myNbExt = 1; |
797 | } |
7fd59977 |
798 | } |
7fd59977 |
799 | } |
800 | |
801 | |
802 | Standard_Boolean Extrema_ExtElCS::IsDone() const |
803 | { |
804 | return myDone; |
805 | } |
806 | |
807 | |
808 | Standard_Integer Extrema_ExtElCS::NbExt() const |
809 | { |
638ad7f3 |
810 | if (!IsDone()) throw StdFail_NotDone(); |
7fd59977 |
811 | return myNbExt; |
812 | } |
813 | |
814 | Standard_Real Extrema_ExtElCS::SquareDistance(const Standard_Integer N) const |
815 | { |
638ad7f3 |
816 | if (N < 1 || N > NbExt()) |
817 | { |
818 | throw Standard_OutOfRange(); |
819 | } |
820 | |
7fd59977 |
821 | return mySqDist->Value(N); |
822 | } |
823 | |
824 | |
825 | void Extrema_ExtElCS::Points(const Standard_Integer N, |
826 | Extrema_POnCurv& P1, |
827 | Extrema_POnSurf& P2) const |
828 | { |
638ad7f3 |
829 | if (N < 1 || N > NbExt()) |
830 | { |
831 | throw Standard_OutOfRange(); |
832 | } |
833 | |
7fd59977 |
834 | P1 = myPoint1->Value(N); |
835 | P2 = myPoint2->Value(N); |
836 | } |
837 | |
838 | |
839 | Standard_Boolean Extrema_ExtElCS::IsParallel() const |
840 | { |
638ad7f3 |
841 | if (!IsDone()) |
842 | { |
843 | throw StdFail_NotDone(); |
844 | } |
7fd59977 |
845 | return myIsPar; |
846 | } |