de862227a73e2a4f567caff179e134b751e625a6
[occt.git] / src / Extrema / Extrema_ExtElCS.cxx
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
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>
33 #include <IntAna_Quadric.hxx>
34 #include <IntAna_IntConicQuad.hxx>
35
36
37 Extrema_ExtElCS::Extrema_ExtElCS() 
38 {
39   myDone = Standard_False;
40   myIsPar = Standard_False;
41 }
42
43
44 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
45                                  const gp_Pln& S)
46 {
47   Perform(C, S);
48 }
49
50
51
52 void 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
71 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
72                                  const gp_Cylinder& S)
73 {
74   Perform(C, S);
75 }
76
77
78
79 void 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();
87   gp_Pnt Origin = Pos.Location();
88   gp_Pnt LineOrig = C.Location();
89
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);
94     myPoint1 = new Extrema_HArray1OfPOnCurv(1, 1);
95     myPoint2 = new Extrema_HArray1OfPOnSurf(1, 1);
96     Standard_Real aDist = sqrt(Extrem.SquareDistance(1)) - radius;
97     mySqDist->SetValue(1, aDist * aDist);
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);
121     myDone = Standard_True;
122     myIsPar = Standard_True;
123   }
124   else {
125     Standard_Integer i;
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         }
146       }
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         }
174       }
175     }
176     myDone = Standard_True;
177   }
178
179 }
180
181
182
183 Extrema_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)
193 void Extrema_ExtElCS::Perform(const gp_Lin& ,
194                               const gp_Cone& )
195 {
196   Standard_NotImplemented::Raise();
197
198 }
199
200
201
202 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
203                                  const gp_Sphere& S)
204 {
205   Perform(C, S);
206 }
207
208
209
210 void 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
241 Extrema_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)
251 void Extrema_ExtElCS::Perform(const gp_Lin& ,
252                               const gp_Torus& )
253 {
254   Standard_NotImplemented::Raise();
255
256 }
257
258
259 //        Circle-?
260
261 Extrema_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)
271 void Extrema_ExtElCS::Perform(const gp_Circ& ,
272                               const gp_Pln& )
273 {
274   Standard_NotImplemented::Raise();
275
276 }
277
278
279
280 Extrema_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.
290 void 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();
311       gp_Pnt           aCenter  = C.Location();
312       Standard_Integer i;
313       Standard_Integer aCurI    = 1;
314       Standard_Real    aTolConf = Precision::Confusion();
315       Standard_Real    aCylRad  = S.Radius();
316
317       // Check whether two objects have intersection points
318       IntAna_Quadric aCylQuad(S);
319       IntAna_IntConicQuad aCircCylInter(C, aCylQuad);
320       Standard_Integer aNbInter = aCircCylInter.NbPoints();
321       if (!aCircCylInter.IsDone())
322         aNbInter = 0;
323
324       // Compute the extremas.
325       myNbExt  =     2*aNbExt + aNbInter;
326       mySqDist  = new TColStd_HArray1OfReal(1, myNbExt);
327       myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
328       myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
329
330       for (i = 1; i <= aNbExt; i++) {
331         Extrema_POnCurv aPOnAxis;
332         Extrema_POnCurv aPOnCirc;
333         Standard_Real   aSqDist = anExtC.SquareDistance(i);
334         Standard_Real   aDist = sqrt (aSqDist);
335
336         anExtC.Points(i, aPOnAxis, aPOnCirc);
337
338         if (aSqDist <= (aTolConf * aTolConf)) {
339           myNbExt -= 2;
340           continue;
341         }
342
343         gp_Dir aDir(aPOnAxis.Value().XYZ().Subtracted(aPOnCirc.Value().XYZ()));
344         Standard_Real aShift[2] = { aDist + aCylRad, aDist - aCylRad };
345         Standard_Integer j;
346
347         for (j = 0; j < 2; j++) {
348           gp_Vec aVec(aDir);
349           gp_Pnt aPntOnCyl;
350
351           aVec.Multiply(aShift[j]);
352           aPntOnCyl = aPOnCirc.Value().Translated(aVec);
353
354           Standard_Real aU;
355           Standard_Real aV;
356
357           ElSLib::Parameters(S, aPntOnCyl, aU, aV);
358
359           Extrema_POnSurf aPOnSurf(aU, aV, aPntOnCyl);
360
361           myPoint1->SetValue(aCurI, aPOnCirc);
362           myPoint2->SetValue(aCurI, aPOnSurf);
363           mySqDist->SetValue(aCurI++, aShift[j] * aShift[j]);
364         }
365       }
366
367       // Adding intersection points to the list of extremas
368       for (i=1; i<=aNbInter; i++)
369       {
370         Standard_Real aU;
371         Standard_Real aV;
372
373         gp_Pnt aInterPnt = aCircCylInter.Point(i);
374
375         aU = ElCLib::Parameter(C, aInterPnt);
376         Extrema_POnCurv aPOnCirc(aU, aInterPnt);
377
378         ElSLib::Parameters(S, aInterPnt, aU, aV);
379         Extrema_POnSurf aPOnCyl(aU, aV, aInterPnt);
380         myPoint1->SetValue(aCurI, aPOnCirc);
381         myPoint2->SetValue(aCurI, aPOnCyl);
382         mySqDist->SetValue(aCurI++, 0.0);
383       }
384     }
385
386     myDone = Standard_True;
387   }
388 }
389 //  Modified by skv - Thu Jul  7 14:37:05 2005 OCC9134 End
390
391
392
393 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
394                                  const gp_Cone& S)
395 {
396   Perform(C, S);
397 }
398
399
400
401 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
402 //                       const gp_Cone& S)
403 void Extrema_ExtElCS::Perform(const gp_Circ& ,
404                          const gp_Cone& )
405 {
406   Standard_NotImplemented::Raise();
407
408 }
409
410
411
412 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
413                                  const gp_Sphere& S)
414 {
415   Perform(C, S);
416 }
417
418
419
420 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
421 //                            const gp_Sphere& S)
422 void Extrema_ExtElCS::Perform(const gp_Circ& ,
423                               const gp_Sphere& )
424 {
425   Standard_NotImplemented::Raise();
426
427 }
428
429 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
430                                  const gp_Torus& S)
431 {
432   Perform(C, S);
433 }
434
435
436
437 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
438 //                            const gp_Torus& S)
439 void Extrema_ExtElCS::Perform(const gp_Circ& ,
440                               const gp_Torus& )
441 {
442   Standard_NotImplemented::Raise();
443
444 }
445
446 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Hypr& C,
447                                  const gp_Pln& S)
448 {
449   Perform(C, S);
450 }
451
452
453
454 void Extrema_ExtElCS::Perform(const gp_Hypr& C,
455                               const gp_Pln& S)
456 {
457   myDone = Standard_True;
458   myIsPar = Standard_False;
459
460   gp_Ax2 Pos = C.Position();
461   gp_Dir NHypr = Pos.Direction();
462   gp_Dir NPln = S.Axis().Direction();
463
464   if (NHypr.IsParallel(NPln, Precision::Angular())) {
465
466     mySqDist = new TColStd_HArray1OfReal(1, 1);
467     mySqDist->SetValue(1, S.SquareDistance(C.Location()));
468     myIsPar = Standard_True;
469
470   }
471   else {
472
473     gp_Dir XDir = Pos.XDirection();
474     gp_Dir YDir = Pos.YDirection();
475
476     Standard_Real A = C.MinorRadius()*(NPln.Dot(YDir)); 
477     Standard_Real B = C.MajorRadius()*(NPln.Dot(XDir)); 
478
479     if(Abs(B) > Abs(A)) {
480       Standard_Real T = -0.5 * Log((A+B)/(B-A));
481       gp_Pnt Ph = ElCLib::HyperbolaValue(T, Pos, C.MajorRadius(), C.MinorRadius());
482       Extrema_POnCurv PC(T, Ph);
483       myPoint1 = new Extrema_HArray1OfPOnCurv(1,1);
484       myPoint1->SetValue(1, PC);
485
486       mySqDist = new TColStd_HArray1OfReal(1, 1);
487       mySqDist->SetValue(1, S.SquareDistance(Ph));
488
489       Standard_Real U, V;
490       ElSLib::PlaneParameters(S.Position(), Ph, U, V);
491       gp_Pnt Pp = ElSLib::PlaneValue(U, V, S.Position());
492       Extrema_POnSurf PS(U, V, Pp);
493       myPoint2 = new Extrema_HArray1OfPOnSurf(1,1);
494       myPoint2->SetValue(1, PS);
495
496       myNbExt = 1;
497     }
498     else {
499       myNbExt = 0;
500     }
501
502   }
503   
504 }
505
506
507 Standard_Boolean Extrema_ExtElCS::IsDone() const
508 {
509   return myDone;
510 }
511
512
513 Standard_Integer Extrema_ExtElCS::NbExt() const
514 {
515   if (myIsPar) StdFail_InfiniteSolutions::Raise();
516   return myNbExt;
517 }
518
519 Standard_Real Extrema_ExtElCS::SquareDistance(const Standard_Integer N) const
520 {
521   if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
522   return mySqDist->Value(N);
523 }
524
525
526 void Extrema_ExtElCS::Points(const Standard_Integer N,
527                              Extrema_POnCurv& P1,
528                              Extrema_POnSurf& P2) const
529 {
530   if (myIsPar) StdFail_InfiniteSolutions::Raise();
531   P1 = myPoint1->Value(N);
532   P2 = myPoint2->Value(N);
533 }
534
535
536 Standard_Boolean Extrema_ExtElCS::IsParallel() const
537 {
538   return myIsPar;
539 }