1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
20 // Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134
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>
33 #include <IntAna_Quadric.hxx>
34 #include <IntAna_IntConicQuad.hxx>
37 Extrema_ExtElCS::Extrema_ExtElCS()
39 myDone = Standard_False;
40 myIsPar = Standard_False;
44 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
52 void Extrema_ExtElCS::Perform(const gp_Lin& C,
55 myDone = Standard_True;
56 myIsPar = Standard_False;
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;
71 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
79 void Extrema_ExtElCS::Perform(const gp_Lin& C,
82 myDone = Standard_False;
84 myIsPar = Standard_False;
86 gp_Ax3 Pos = S.Position();
87 gp_Pnt Origin = Pos.Location();
88 gp_Pnt LineOrig = C.Location();
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());
102 gp_Pnt LinPoint = LineOrig.Translated(w * aDirVec);
103 Extrema_POnCurv PonC(w, LinPoint);
104 myPoint1->SetValue(1, PonC);
106 gp_Vec OrigToLine(Origin, LinPoint);
107 if (OrigToLine.Magnitude() <= gp::Resolution())
111 CylPoint = ElSLib::Value(u, v, S);
115 OrigToLine.Normalize();
116 CylPoint = Origin.Translated(radius * OrigToLine);
117 ElSLib::CylinderParameters(Pos, radius, CylPoint, u, v);
119 Extrema_POnSurf PonS(u, v, CylPoint);
120 myPoint2->SetValue(1, PonS);
121 myDone = Standard_True;
122 myIsPar = Standard_True;
127 Extrema_POnCurv myPOnC1, myPOnC2;
128 Extrem.Points(1, myPOnC1, myPOnC2);
129 gp_Pnt PonAxis = myPOnC1.Value();
130 gp_Pnt PC = myPOnC2.Value();
132 // line is tangent or outside of the cylunder -- single solution
133 if (radius - PonAxis.Distance(PC) < Precision::PConfusion())
135 Extrema_ExtPElS ExPS(PC, S, Precision::Confusion());
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()));
148 // line intersects the cylinder
151 IntAna_Quadric theQuadric(S);
152 IntAna_IntConicQuad Inters(C, theQuadric);
155 myNbExt = Inters.NbPoints();
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++)
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);
176 myDone = Standard_True;
183 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
191 //void Extrema_ExtElCS::Perform(const gp_Lin& C,
193 void Extrema_ExtElCS::Perform(const gp_Lin& ,
196 Standard_NotImplemented::Raise();
202 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
210 void Extrema_ExtElCS::Perform(const gp_Lin& C,
213 myDone = Standard_False;
215 myIsPar = Standard_False;
217 gp_Pnt O = S.Location();
219 Extrema_ExtPElC Extrem(O, C, Precision::Angular(), RealFirst(), RealLast());
222 if (Extrem.IsDone()) {
223 Extrema_POnCurv myPOnC1 = Extrem.Point(1);
224 Extrema_ExtPElS ExPS(myPOnC1.Value(), S, Precision::Confusion());
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;
241 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Lin& C,
249 //void Extrema_ExtElCS::Perform(const gp_Lin& C,
250 // const gp_Torus& S)
251 void Extrema_ExtElCS::Perform(const gp_Lin& ,
254 Standard_NotImplemented::Raise();
261 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
269 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
271 void Extrema_ExtElCS::Perform(const gp_Circ& ,
274 Standard_NotImplemented::Raise();
280 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
281 const gp_Cylinder& S)
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)
293 myDone = Standard_False;
294 myIsPar = Standard_False;
297 // Get an axis line of the cylinder.
298 gp_Lin anAxis(S.Axis());
300 // Compute extrema between the circle and the line.
301 Extrema_ExtElC anExtC(anAxis, C, 0.);
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);
310 Standard_Integer aNbExt = anExtC.NbExt();
312 Standard_Integer aCurI = 1;
313 Standard_Real aTolConf = Precision::Confusion();
314 Standard_Real aCylRad = S.Radius();
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())
323 // Compute the extremas.
324 myNbExt = 2*aNbExt + aNbInter;
325 mySqDist = new TColStd_HArray1OfReal(1, myNbExt);
326 myPoint1 = new Extrema_HArray1OfPOnCurv(1, myNbExt);
327 myPoint2 = new Extrema_HArray1OfPOnSurf(1, myNbExt);
329 for (i = 1; i <= aNbExt; i++) {
330 Extrema_POnCurv aPOnAxis;
331 Extrema_POnCurv aPOnCirc;
332 Standard_Real aSqDist = anExtC.SquareDistance(i);
333 Standard_Real aDist = sqrt (aSqDist);
335 anExtC.Points(i, aPOnAxis, aPOnCirc);
337 if (aSqDist <= (aTolConf * aTolConf)) {
342 gp_Dir aDir(aPOnAxis.Value().XYZ().Subtracted(aPOnCirc.Value().XYZ()));
343 Standard_Real aShift[2] = { aDist + aCylRad, aDist - aCylRad };
346 for (j = 0; j < 2; j++) {
350 aVec.Multiply(aShift[j]);
351 aPntOnCyl = aPOnCirc.Value().Translated(aVec);
356 ElSLib::Parameters(S, aPntOnCyl, aU, aV);
358 Extrema_POnSurf aPOnSurf(aU, aV, aPntOnCyl);
360 myPoint1->SetValue(aCurI, aPOnCirc);
361 myPoint2->SetValue(aCurI, aPOnSurf);
362 mySqDist->SetValue(aCurI++, aShift[j] * aShift[j]);
366 // Adding intersection points to the list of extremas
367 for (i=1; i<=aNbInter; i++)
372 gp_Pnt aInterPnt = aCircCylInter.Point(i);
374 aU = ElCLib::Parameter(C, aInterPnt);
375 Extrema_POnCurv aPOnCirc(aU, aInterPnt);
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);
385 myDone = Standard_True;
388 // Modified by skv - Thu Jul 7 14:37:05 2005 OCC9134 End
392 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
400 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
402 void Extrema_ExtElCS::Perform(const gp_Circ& ,
405 Standard_NotImplemented::Raise();
411 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
419 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
420 // const gp_Sphere& S)
421 void Extrema_ExtElCS::Perform(const gp_Circ& ,
424 Standard_NotImplemented::Raise();
428 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Circ& C,
436 //void Extrema_ExtElCS::Perform(const gp_Circ& C,
437 // const gp_Torus& S)
438 void Extrema_ExtElCS::Perform(const gp_Circ& ,
441 Standard_NotImplemented::Raise();
445 Extrema_ExtElCS::Extrema_ExtElCS(const gp_Hypr& C,
453 void Extrema_ExtElCS::Perform(const gp_Hypr& C,
456 myDone = Standard_True;
457 myIsPar = Standard_False;
459 gp_Ax2 Pos = C.Position();
460 gp_Dir NHypr = Pos.Direction();
461 gp_Dir NPln = S.Axis().Direction();
463 if (NHypr.IsParallel(NPln, Precision::Angular())) {
465 mySqDist = new TColStd_HArray1OfReal(1, 1);
466 mySqDist->SetValue(1, S.SquareDistance(C.Location()));
467 myIsPar = Standard_True;
472 gp_Dir XDir = Pos.XDirection();
473 gp_Dir YDir = Pos.YDirection();
475 Standard_Real A = C.MinorRadius()*(NPln.Dot(YDir));
476 Standard_Real B = C.MajorRadius()*(NPln.Dot(XDir));
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);
485 mySqDist = new TColStd_HArray1OfReal(1, 1);
486 mySqDist->SetValue(1, S.SquareDistance(Ph));
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);
506 Standard_Boolean Extrema_ExtElCS::IsDone() const
512 Standard_Integer Extrema_ExtElCS::NbExt() const
514 if (myIsPar) StdFail_InfiniteSolutions::Raise();
518 Standard_Real Extrema_ExtElCS::SquareDistance(const Standard_Integer N) const
520 if (myIsPar && N != 1) StdFail_InfiniteSolutions::Raise();
521 return mySqDist->Value(N);
525 void Extrema_ExtElCS::Points(const Standard_Integer N,
527 Extrema_POnSurf& P2) const
529 if (myIsPar) StdFail_InfiniteSolutions::Raise();
530 P1 = myPoint1->Value(N);
531 P2 = myPoint2->Value(N);
535 Standard_Boolean Extrema_ExtElCS::IsParallel() const