0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / Extrema / Extrema_ExtElCS.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2012 OPEN CASCADE SAS
3//
4// The content of this file is subject to the Open CASCADE Technology Public
5// License Version 6.5 (the "License"). You may not use the content of this file
6// except in compliance with the License. Please obtain a copy of the License
7// at http://www.opencascade.org and read it completely before using this file.
8//
9// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11//
12// The Original Code and all software distributed under the License is
13// distributed on an "AS IS" basis, without warranty of any kind, and the
14// Initial Developer hereby disclaims all such warranties, including without
15// limitation, any warranties of merchantability, fitness for a particular
16// purpose or non-infringement. Please see the License for the specific terms
17// and conditions governing the rights and limitations under the License.
18
7fd59977 19
20// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134
21
22#include <Extrema_ExtElCS.ixx>
23#include <Extrema_ExtPElS.hxx>
24#include <Extrema_ExtPElC.hxx>
25#include <Extrema_ExtElC.hxx>
26#include <Extrema_POnCurv.hxx>
27#include <Standard_NotImplemented.hxx>
28#include <StdFail_InfiniteSolutions.hxx>
29#include <Precision.hxx>
30#include <ElSLib.hxx>
31#include <ElCLib.hxx>
32#include <gp_Vec.hxx>
f34cd0d1 33#include <IntAna_Quadric.hxx>
34#include <IntAna_IntConicQuad.hxx>
7fd59977 35
36
37Extrema_ExtElCS::Extrema_ExtElCS()
38{
39 myDone = Standard_False;
40 myIsPar = Standard_False;
41}
42
43
44Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
45 const gp_Pln& S)
46{
47 Perform(C, S);
48}
49
50
51
52void Extrema_ExtElCS::Perform(const gp_Lin& C,
53 const gp_Pln& S)
54{
55 myDone = Standard_True;
56 myIsPar = Standard_False;
57
58 if (C.Direction().IsNormal(S.Axis().Direction(),
59 Precision::Angular())) {
60 mySqDist = new TColStd_HArray1OfReal(1, 1);
61 mySqDist->SetValue(1, S.SquareDistance(C));
62 myIsPar = Standard_True;
63 }
64 else {
65 myNbExt = 0;
66 }
67
68}
69
70
71Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
72 const gp_Cylinder& S)
73{
74 Perform(C, S);
75}
76
77
78
79void Extrema_ExtElCS::Perform(const gp_Lin& C,
80 const gp_Cylinder& S)
81{
82 myDone = Standard_False;
83 myNbExt = 0;
84 myIsPar = Standard_False;
85
86 gp_Ax3 Pos = S.Position();
f34cd0d1 87 gp_Pnt Origin = Pos.Location();
88 gp_Pnt LineOrig = C.Location();
89
7fd59977 90 Standard_Real radius = S.Radius();
91 Extrema_ExtElC Extrem(gp_Lin(Pos.Axis()), C, Precision::Angular());
92 if (Extrem.IsParallel()) {
93 mySqDist = new TColStd_HArray1OfReal(1, 1);
f34cd0d1 94 myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1);
95 myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1);
96 Standard_Real aDist = sqrt(Extrem.SquareDistance(1)) - radius;
7fd59977 97 mySqDist->SetValue(1, aDist * aDist);
f34cd0d1 98 Standard_Real u, v, w;
99 gp_Vec aVec(LineOrig, Origin);
100 gp_Vec aDirVec(C.Direction());
101 w = aVec*aDirVec;
102 gp_Pnt LinPoint = LineOrig.Translated(w * aDirVec);
103 Extrema_POnCurv PonC(w, LinPoint);
104 myPoint1->SetValue(1, PonC);
105 gp_Pnt CylPoint;
106 gp_Vec OrigToLine(Origin, LinPoint);
107 if (OrigToLine.Magnitude() <= gp::Resolution())
108 {
109 u = 0.;
110 v = 0.;
111 CylPoint = ElSLib::Value(u, v, S);
112 }
113 else
114 {
115 OrigToLine.Normalize();
116 CylPoint = Origin.Translated(radius * OrigToLine);
117 ElSLib::CylinderParameters(Pos, radius, CylPoint, u, v);
118 }
119 Extrema_POnSurf PonS(u, v, CylPoint);
120 myPoint2->SetValue(1, PonS);
7fd59977 121 myDone = Standard_True;
122 myIsPar = Standard_True;
123 }
124 else {
125 Standard_Integer i;
f34cd0d1 126
127 Extrema_POnCurv myPOnC1, myPOnC2;
128 Extrem.Points(1, myPOnC1, myPOnC2);
129 gp_Pnt PonAxis = myPOnC1.Value();
130 gp_Pnt PC = myPOnC2.Value();
131
132 // line is tangent or outside of the cylunder -- single solution
133 if (radius - PonAxis.Distance(PC) < Precision::PConfusion())
134 {
135 Extrema_ExtPElS ExPS(PC, S, Precision::Confusion());
136 if (ExPS.IsDone()) {
137 myNbExt = ExPS.NbExt();
138 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
139 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
140 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
141 for (i = 1; i <= myNbExt; i++) {
142 myPoint1->SetValue(i, myPOnC2);
143 myPoint2->SetValue(i, ExPS.Point(i));
144 mySqDist->SetValue(i,(myPOnC2.Value()).SquareDistance(ExPS.Point(i).Value()));
145 }
7fd59977 146 }
f34cd0d1 147 }
148 // line intersects the cylinder
149 else
150 {
151 IntAna_Quadric theQuadric(S);
152 IntAna_IntConicQuad Inters(C, theQuadric);
153 if (Inters.IsDone())
154 {
155 myNbExt = Inters.NbPoints();
156 if (myNbExt > 0)
157 {
158 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
159 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
160 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
161 Standard_Real u, v, w;
162 for (i = 1; i <= myNbExt; i++)
163 {
164 mySqDist->SetValue(i, 0.);
165 gp_Pnt P_int = Inters.Point(i);
166 w = Inters.ParamOnConic(i);
167 Extrema_POnCurv PonC(w, P_int);
168 myPoint1->SetValue(i, PonC);
169 ElSLib::CylinderParameters(Pos, radius, P_int, u, v);
170 Extrema_POnSurf PonS(u, v, P_int);
171 myPoint2->SetValue(i, PonS);
172 }
173 }
7fd59977 174 }
7fd59977 175 }
f34cd0d1 176 myDone = Standard_True;
7fd59977 177 }
178
179}
180
181
182
183Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
184 const gp_Cone& S)
185{
186 Perform(C, S);
187}
188
189
190
191//void Extrema_ExtElCS::Perform(const gp_Lin& C,
192// const gp_Cone& S)
193void Extrema_ExtElCS::Perform(const gp_Lin& ,
194 const gp_Cone& )
195{
196 Standard_NotImplemented::Raise();
197
198}
199
200
201
202Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
203 const gp_Sphere& S)
204{
205 Perform(C, S);
206}
207
208
209
210void Extrema_ExtElCS::Perform(const gp_Lin& C,
211 const gp_Sphere& S)
212{
213 myDone = Standard_False;
214 myNbExt = 0;
215 myIsPar = Standard_False;
216
217 gp_Pnt O = S.Location();
218
219 Extrema_ExtPElC Extrem(O, C, Precision::Angular(), RealFirst(), RealLast());
220
221 Standard_Integer i;
222 if (Extrem.IsDone()) {
223 Extrema_POnCurv myPOnC1 = Extrem.Point(1);
224 Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion());
225 if (ExPS.IsDone()) {
226 myNbExt = ExPS.NbExt();
227 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
228 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
229 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
230 for (i = 1; i <= myNbExt; i++) {
231 myPoint1->SetValue(i, myPOnC1);
232 myPoint2->SetValue(i, ExPS.Point(i));
233 mySqDist->SetValue(i,(myPOnC1.Value()).SquareDistance(ExPS.Point(i).Value()));
234 myDone = Standard_True;
235 }
236 }
237 }
238}
239
240
241Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
242 const gp_Torus& S)
243{
244 Perform(C, S);
245}
246
247
248
249//void Extrema_ExtElCS::Perform(const gp_Lin& C,
250// const gp_Torus& S)
251void Extrema_ExtElCS::Perform(const gp_Lin& ,
252 const gp_Torus& )
253{
254 Standard_NotImplemented::Raise();
255
256}
257
258
259// Circle-?
260
261Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
262 const gp_Pln& S)
263{
264 Perform(C, S);
265}
266
267
268
269//void Extrema_ExtElCS::Perform(const gp_Circ& C,
270// const gp_Pln& S)
271void Extrema_ExtElCS::Perform(const gp_Circ& ,
272 const gp_Pln& )
273{
274 Standard_NotImplemented::Raise();
275
276}
277
278
279
280Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
281 const gp_Cylinder& S)
282{
283 Perform(C, S);
284}
285
286
287
288// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 Begin
289// Implementation of the method.
290void Extrema_ExtElCS::Perform(const gp_Circ& C,
291 const gp_Cylinder& S)
292{
293 myDone = Standard_False;
294 myIsPar = Standard_False;
295 myNbExt = 0;
296
297 // Get an axis line of the cylinder.
298 gp_Lin anAxis(S.Axis());
299
300 // Compute extrema between the circle and the line.
301 Extrema_ExtElC anExtC(anAxis, C, 0.);
302
303 if (anExtC.IsDone()) {
304 if (anExtC.IsParallel()) {
305 myIsPar = Standard_True;
306 mySqDist = new TColStd_HArray1OfReal(1, 1);
307 Standard_Real aDist = sqrt (anExtC.SquareDistance(1)) - S.Radius();
308 mySqDist->SetValue(1, aDist * aDist);
309 } else {
310 Standard_Integer aNbExt = anExtC.NbExt();
7fd59977 311 Standard_Integer i;
312 Standard_Integer aCurI = 1;
313 Standard_Real aTolConf = Precision::Confusion();
314 Standard_Real aCylRad = S.Radius();
315
19875353 316 // Check whether two objects have intersection points
317 IntAna_Quadric aCylQuad(S);
318 IntAna_IntConicQuad aCircCylInter(C, aCylQuad);
319 Standard_Integer aNbInter = aCircCylInter.NbPoints();
320 if (!aCircCylInter.IsDone())
321 aNbInter = 0;
322
7fd59977 323 // Compute the extremas.
19875353 324 myNbExt = 2*aNbExt + aNbInter;
7fd59977 325 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
326 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
327 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
328
329 for (i = 1; i <= aNbExt; i++) {
19875353 330 Extrema_POnCurv aPOnAxis;
331 Extrema_POnCurv aPOnCirc;
332 Standard_Real aSqDist = anExtC.SquareDistance(i);
333 Standard_Real aDist = sqrt (aSqDist);
334
335 anExtC.Points(i, aPOnAxis, aPOnCirc);
336
337 if (aSqDist <= (aTolConf * aTolConf)) {
338 myNbExt -= 2;
339 continue;
340 }
341
342 gp_Dir aDir(aPOnAxis.Value().XYZ().Subtracted(aPOnCirc.Value().XYZ()));
343 Standard_Real aShift[2] = { aDist + aCylRad, aDist - aCylRad };
344 Standard_Integer j;
7fd59977 345
19875353 346 for (j = 0; j < 2; j++) {
347 gp_Vec aVec(aDir);
348 gp_Pnt aPntOnCyl;
7fd59977 349
19875353 350 aVec.Multiply(aShift[j]);
351 aPntOnCyl = aPOnCirc.Value().Translated(aVec);
7fd59977 352
19875353 353 Standard_Real aU;
354 Standard_Real aV;
7fd59977 355
19875353 356 ElSLib::Parameters(S, aPntOnCyl, aU, aV);
7fd59977 357
19875353 358 Extrema_POnSurf aPOnSurf(aU, aV, aPntOnCyl);
7fd59977 359
19875353 360 myPoint1->SetValue(aCurI, aPOnCirc);
361 myPoint2->SetValue(aCurI, aPOnSurf);
362 mySqDist->SetValue(aCurI++, aShift[j] * aShift[j]);
363 }
364 }
365
366 // Adding intersection points to the list of extremas
367 for (i=1; i<=aNbInter; i++)
368 {
369 Standard_Real aU;
370 Standard_Real aV;
7fd59977 371
19875353 372 gp_Pnt aInterPnt = aCircCylInter.Point(i);
7fd59977 373
19875353 374 aU = ElCLib::Parameter(C, aInterPnt);
375 Extrema_POnCurv aPOnCirc(aU, aInterPnt);
7fd59977 376
19875353 377 ElSLib::Parameters(S, aInterPnt, aU, aV);
378 Extrema_POnSurf aPOnCyl(aU, aV, aInterPnt);
379 myPoint1->SetValue(aCurI, aPOnCirc);
380 myPoint2->SetValue(aCurI, aPOnCyl);
381 mySqDist->SetValue(aCurI++, 0.0);
7fd59977 382 }
383 }
384
385 myDone = Standard_True;
386 }
387}
388// Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 End
389
390
391
392Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
393 const gp_Cone& S)
394{
395 Perform(C, S);
396}
397
398
399
400//void Extrema_ExtElCS::Perform(const gp_Circ& C,
401// const gp_Cone& S)
402void Extrema_ExtElCS::Perform(const gp_Circ& ,
403 const gp_Cone& )
404{
405 Standard_NotImplemented::Raise();
406
407}
408
409
410
411Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
412 const gp_Sphere& S)
413{
414 Perform(C, S);
415}
416
417
418
419//void Extrema_ExtElCS::Perform(const gp_Circ& C,
420// const gp_Sphere& S)
421void Extrema_ExtElCS::Perform(const gp_Circ& ,
422 const gp_Sphere& )
423{
424 Standard_NotImplemented::Raise();
425
426}
427
428Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
429 const gp_Torus& S)
430{
431 Perform(C, S);
432}
433
434
435
436//void Extrema_ExtElCS::Perform(const gp_Circ& C,
437// const gp_Torus& S)
438void Extrema_ExtElCS::Perform(const gp_Circ& ,
439 const gp_Torus& )
440{
441 Standard_NotImplemented::Raise();
442
443}
444
445Extrema_ExtElCS::Extrema_ExtElCS(const gp_Hypr& C,
446 const gp_Pln& S)
447{
448 Perform(C, S);
449}
450
451
452
453void Extrema_ExtElCS::Perform(const gp_Hypr& C,
454 const gp_Pln& S)
455{
456 myDone = Standard_True;
457 myIsPar = Standard_False;
458
459 gp_Ax2 Pos = C.Position();
460 gp_Dir NHypr = Pos.Direction();
461 gp_Dir NPln = S.Axis().Direction();
462
463 if (NHypr.IsParallel(NPln, Precision::Angular())) {
464
465 mySqDist = new TColStd_HArray1OfReal(1, 1);
466 mySqDist->SetValue(1, S.SquareDistance(C.Location()));
467 myIsPar = Standard_True;
468
469 }
470 else {
471
472 gp_Dir XDir = Pos.XDirection();
473 gp_Dir YDir = Pos.YDirection();
474
475 Standard_Real A = C.MinorRadius()*(NPln.Dot(YDir));
476 Standard_Real B = C.MajorRadius()*(NPln.Dot(XDir));
477
478 if(Abs(B) > Abs(A)) {
479 Standard_Real T = -0.5 * Log((A+B)/(B-A));
480 gp_Pnt Ph = ElCLib::HyperbolaValue(T, Pos, C.MajorRadius(), C.MinorRadius());
481 Extrema_POnCurv PC(T, Ph);
482 myPoint1 = new Extrema_HArray1OfPOnCurv(1,1);
483 myPoint1->SetValue(1, PC);
484
485 mySqDist = new TColStd_HArray1OfReal(1, 1);
486 mySqDist->SetValue(1, S.SquareDistance(Ph));
487
488 Standard_Real U, V;
489 ElSLib::PlaneParameters(S.Position(), Ph, U, V);
490 gp_Pnt Pp = ElSLib::PlaneValue(U, V, S.Position());
491 Extrema_POnSurf PS(U, V, Pp);
492 myPoint2 = new Extrema_HArray1OfPOnSurf(1,1);
493 myPoint2->SetValue(1, PS);
494
495 myNbExt = 1;
496 }
497 else {
498 myNbExt = 0;
499 }
500
501 }
502
503}
504
505
506Standard_Boolean Extrema_ExtElCS::IsDone() const
507{
508 return myDone;
509}
510
511
512Standard_Integer Extrema_ExtElCS::NbExt() const
513{
514 if (myIsPar) StdFail_InfiniteSolutions::Raise();
515 return myNbExt;
516}
517
518Standard_Real Extrema_ExtElCS::SquareDistance(const Standard_Integer N) const
519{
520 if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
521 return mySqDist->Value(N);
522}
523
524
525void Extrema_ExtElCS::Points(const Standard_Integer N,
526 Extrema_POnCurv& P1,
527 Extrema_POnSurf& P2) const
528{
529 if (myIsPar) StdFail_InfiniteSolutions::Raise();
530 P1 = myPoint1->Value(N);
531 P2 = myPoint2->Value(N);
532}
533
534
535Standard_Boolean Extrema_ExtElCS::IsParallel() const
536{
537 return myIsPar;
538}