1 // Created on: 1999-09-21
2 // Created by: Edward AGAPOV
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Adaptor3d_HCurve.hxx>
19 #include <GeomAdaptor_HSurfaceOfRevolution.hxx>
21 #include <Extrema_ExtPElC.hxx>
22 #include <Extrema_ExtPRevS.hxx>
23 #include <Extrema_GenExtPS.hxx>
24 #include <Extrema_POnCurv.hxx>
25 #include <Extrema_POnSurf.hxx>
31 #include <gp_Trsf.hxx>
33 #include <Precision.hxx>
34 #include <Standard_OutOfRange.hxx>
35 #include <Standard_Type.hxx>
36 #include <StdFail_NotDone.hxx>
38 IMPLEMENT_STANDARD_RTTIEXT(Extrema_ExtPRevS,Standard_Transient)
40 static gp_Ax2 GetPosition (const GeomAdaptor_SurfaceOfRevolution& S)//const Handle(Adaptor_HCurve)& C)
42 Handle(Adaptor3d_HCurve) C = S.BasisCurve();
44 switch (C->GetType()) {
48 gp_Dir N = S.AxeOfRevolution().Direction();
49 if (N.IsParallel(L.Direction(), Precision::Angular())) {
50 gp_Vec OO (L.Location(), S.AxeOfRevolution().Location());
51 if (OO.Magnitude() <= gp::Resolution()) {
52 OO = gp_Vec(L.Location(), ElCLib::Value(100,L));
53 if (N.IsParallel(OO, Precision::Angular()))
54 return gp_Ax2(); // Line and axe of revolution coinside
61 return gp_Ax2 (L.Location(), N, L.Direction());
64 return C->Circle().Position();
66 return C->Ellipse().Position();
67 case GeomAbs_Hyperbola:
68 return C->Hyperbola().Position();
69 case GeomAbs_Parabola:
70 return C->Parabola().Position();
76 //=======================================================================
77 //function : HasSingularity
79 //=======================================================================
81 static Standard_Boolean HasSingularity(const GeomAdaptor_SurfaceOfRevolution& S)
84 const Handle(Adaptor3d_HCurve) C = S.BasisCurve();
85 gp_Dir N = S.AxeOfRevolution().Direction();
86 gp_Pnt P = S.AxeOfRevolution().Location();
90 P = C->Value(C->FirstParameter());
92 if(L.SquareDistance(P) < Precision::SquareConfusion()) return Standard_True;
94 P = C->Value(C->LastParameter());
96 if(L.SquareDistance(P) < Precision::SquareConfusion()) return Standard_True;
98 return Standard_False;
101 //=============================================================================
103 static void PerformExtPElC (Extrema_ExtPElC& E,
105 const Handle(Adaptor3d_HCurve)& C,
106 const Standard_Real Tol)
108 switch (C->GetType()) {
109 case GeomAbs_Hyperbola:
110 E.Perform(P, C->Hyperbola(), Tol, -Precision::Infinite(),Precision::Infinite());
113 E.Perform(P, C->Line(), Tol, -Precision::Infinite(),Precision::Infinite());
116 E.Perform(P, C->Circle(), Tol, 0.0, 2.0 * M_PI);
118 case GeomAbs_Ellipse:
119 E.Perform(P, C->Ellipse(), Tol, 0.0, 2.0 * M_PI);
121 case GeomAbs_Parabola:
122 E.Perform(P, C->Parabola(), Tol, -Precision::Infinite(),Precision::Infinite());
129 //=======================================================================
130 //function : IsCaseAnalyticallyComputable
132 //=======================================================================
134 static Standard_Boolean IsCaseAnalyticallyComputable
135 (const GeomAbs_CurveType& theType,
136 const gp_Ax2& theCurvePos,
137 const gp_Ax1& AxeOfRevolution)
143 case GeomAbs_Ellipse:
144 case GeomAbs_Hyperbola:
145 case GeomAbs_Parabola:
148 return Standard_False;
150 // the axe of revolution must be in the plane of the curve.
151 gp_Pln pl(theCurvePos.Location(), theCurvePos.Direction());
152 gp_Pnt p1 = AxeOfRevolution.Location();
153 Standard_Real dist = 100., dist2 = dist * dist;
154 Standard_Real aThreshold = Precision::Angular() * Precision::Angular() * dist2;
155 gp_Pnt p2 = AxeOfRevolution.Location().XYZ() + dist * AxeOfRevolution.Direction().XYZ();
157 if((pl.SquareDistance(p1) < aThreshold) &&
158 (pl.SquareDistance(p2) < aThreshold))
159 return Standard_True;
160 return Standard_False;
161 // gp_Vec V (AxeOfRevolution.Location(),theCurvePos.Location());
162 // if (Abs( V * theCurvePos.Direction()) <= gp::Resolution())
163 // return Standard_True;
165 // return Standard_False;
168 //=======================================================================
169 //function : IsOriginalPnt
171 //=======================================================================
173 static Standard_Boolean IsOriginalPnt (const gp_Pnt& P,
174 const Extrema_POnSurf* Points,
175 const Standard_Integer NbPoints)
177 for (Standard_Integer i=1; i<=NbPoints; i++) {
178 if (Points[i-1].Value().IsEqual(P, Precision::Confusion())) {
179 return Standard_False;
182 return Standard_True;
184 //=======================================================================
185 //function : IsExtremum
187 //=======================================================================
189 static Standard_Boolean IsExtremum (const Standard_Real U, const Standard_Real V,
190 const gp_Pnt& P, const Adaptor3d_SurfacePtr& S,
191 gp_Pnt& E, Standard_Real& Dist2,
192 const Standard_Boolean IsVSup,
193 const Standard_Boolean IsMin)
196 Dist2 = P.SquareDistance(E);
198 return (Dist2 < P.SquareDistance(S->Value(U+1,V)) &&
199 Dist2 < P.SquareDistance(S->Value(U-1,V)) &&
200 Dist2 < P.SquareDistance(S->Value(U, IsVSup ? V-1 : V+1)));
202 return (Dist2 > P.SquareDistance(S->Value(U+1,V)) &&
203 Dist2 > P.SquareDistance(S->Value(U-1,V)) &&
204 Dist2 > P.SquareDistance(S->Value(U, IsVSup ? V-1 : V+1)));
206 //=======================================================================
207 //function : Extrema_ExtPRevS
209 //=======================================================================
211 Extrema_ExtPRevS::Extrema_ExtPRevS()
213 myDone = Standard_False;
215 //=======================================================================
216 //function : Extrema_ExtPRevS
218 //=======================================================================
220 Extrema_ExtPRevS::Extrema_ExtPRevS (const gp_Pnt& theP,
221 const Handle(GeomAdaptor_HSurfaceOfRevolution)& theS,
222 const Standard_Real theUmin,
223 const Standard_Real theUsup,
224 const Standard_Real theVmin,
225 const Standard_Real theVsup,
226 const Standard_Real theTolU,
227 const Standard_Real theTolV)
239 //=======================================================================
240 //function : Extrema_ExtPRevS
242 //=======================================================================
244 Extrema_ExtPRevS::Extrema_ExtPRevS (const gp_Pnt& theP,
245 const Handle(GeomAdaptor_HSurfaceOfRevolution)& theS,
246 const Standard_Real theTolU,
247 const Standard_Real theTolV)
250 theS->FirstUParameter(),
251 theS->LastUParameter(),
252 theS->FirstVParameter(),
253 theS->LastVParameter(),
259 //=======================================================================
260 //function : Initialize
262 //=======================================================================
264 void Extrema_ExtPRevS::Initialize (const Handle(GeomAdaptor_HSurfaceOfRevolution)& theS,
265 const Standard_Real theUmin,
266 const Standard_Real theUsup,
267 const Standard_Real theVmin,
268 const Standard_Real theVsup,
269 const Standard_Real theTolU,
270 const Standard_Real theTolV)
276 Handle(Adaptor3d_HCurve) anACurve = theS->BasisCurve();
281 myPosition = GetPosition (theS->ChangeSurface());
282 myIsAnalyticallyComputable =
283 IsCaseAnalyticallyComputable (anACurve->GetType(), myPosition, theS->AxeOfRevolution());
286 if (!myIsAnalyticallyComputable)
288 Standard_Integer aNbu = 32, aNbv = 32;
290 if (HasSingularity (theS->ChangeSurface()))
295 myExtPS.Initialize (theS->ChangeSurface(),
306 //=======================================================================
309 //=======================================================================
311 void Extrema_ExtPRevS::Perform(const gp_Pnt& P)
313 myDone = Standard_False;
316 if (!myIsAnalyticallyComputable) {
319 myDone = myExtPS.IsDone();
320 myNbExt = myExtPS.NbExt();
324 Handle(Adaptor3d_HCurve) anACurve = myS->BasisCurve();
326 gp_Ax1 Ax = myS->AxeOfRevolution();
327 gp_Vec Dir = Ax.Direction(), Z = myPosition.Direction();
328 gp_Pnt O = Ax.Location();
330 Standard_Real OPdir = gp_Vec(O,P).Dot(Dir);
331 gp_Pnt Pp = P.Translated(Dir.Multiplied(-OPdir));
332 if (O.IsEqual(Pp,Precision::Confusion())) // P is on the AxeOfRevolution
337 Standard_Real OPpz = gp_Vec(O,Pp).Dot(Z);
338 if (Abs(OPpz) <= gp::Resolution()) {
343 Ppp = Pp.Translated(Z.Multiplied(-OPpz));
344 if (O.IsEqual(Ppp,Precision::Confusion()))
347 U = gp_Vec(O,Ppp).AngleWithRef(gp_Vec(O,Pp),Dir);
351 gp_Vec OPpp (O,Ppp), OPq (O, myS->Value(M_PI/2,0));
353 if (Abs(OPq.Magnitude()) <= gp::Resolution())
354 OPq = gp_Vec(O, myS->Value(M_PI/2,anACurve->LastParameter()/10));
355 if (OPpp.AngleWithRef(OPq,Dir) < 0)
360 T.SetRotation(Ax, -U);
361 P1 = P.Transformed(T);
367 Extrema_ExtPElC anExt;
368 PerformExtPElC(anExt, P1, anACurve, mytolv);
370 if (anExt.IsDone()) {
371 myDone = Standard_True;
372 for (i=1; i<=anExt.NbExt(); i++) {
373 Extrema_POnCurv POC=anExt.Point(i);
376 // if ( !IsExtremum (U, V = myvsup, P, myS, E, Dist2,
377 // Standard_True, anExt.IsMin(i))) continue;
378 Standard_Real newV = myvsup;
380 if((anACurve->GetType() == GeomAbs_Circle) ||
381 (anACurve->GetType() == GeomAbs_Ellipse)) {
382 newV = ElCLib::InPeriod(V, myvinf, myvinf + 2. * M_PI);
387 if (newV + mytolv < myvinf) {
389 } else if (newV < myvinf) {
396 if ( !IsExtremum (U, V, P, &(myS->ChangeSurface()), E, Dist2,
397 Standard_True, anExt.IsMin(i))) {
400 } else if (V < myvinf) {
401 // if ( !IsExtremum (U, V = myvinf, P, myS, E, Dist2,
402 // Standard_False, anExt.IsMin(i))) continue;
404 Standard_Real newV = myvinf;
406 if((anACurve->GetType() == GeomAbs_Circle) ||
407 (anACurve->GetType() == GeomAbs_Ellipse)) {
408 newV = ElCLib::InPeriod(V, myvsup - 2. * M_PI, myvsup);
413 if (newV - mytolv > myvsup) {
415 } else if (newV > myvsup) {
422 if ( !IsExtremum (U, V, P, &(myS->ChangeSurface()), E, Dist2,
423 Standard_False, anExt.IsMin(i))) continue;
426 Dist2 = P.SquareDistance(E);
428 if (IsOriginalPnt(E, myPoint, myNbExt)) {
429 myPoint[myNbExt] = Extrema_POnSurf(U,V,E);
430 mySqDist[myNbExt] = Dist2;
435 T.SetRotation(Ax, M_PI);
438 PerformExtPElC(anExt, P1, anACurve, mytolv);
439 if (anExt.IsDone()) {
440 myDone = Standard_True;
444 for (i=1; i<=anExt.NbExt(); i++) {
445 Extrema_POnCurv POC=anExt.Point(i);
448 // if ( !IsExtremum (U, V = myvsup, P, myS, E, Dist2,
449 // Standard_True, anExt.IsMin(i))) continue;
451 Standard_Real newV = myvsup;
453 if((anACurve->GetType() == GeomAbs_Circle) ||
454 (anACurve->GetType() == GeomAbs_Ellipse)) {
455 newV = ElCLib::InPeriod(V, myvinf, myvinf + 2. * M_PI);
460 if (newV + mytolv < myvinf) {
462 } else if (newV < myvinf) {
469 if ( !IsExtremum (U, V, P, &(myS->ChangeSurface()), E, Dist2,
470 Standard_True, anExt.IsMin(i))) continue;
471 } else if (V < myvinf) {
472 // if ( !IsExtremum (U, V = myvinf, P, myS, E, Dist2,
473 // Standard_False, anExt.IsMin(i))) continue;
474 Standard_Real newV = myvinf;
476 if((anACurve->GetType() == GeomAbs_Circle) ||
477 (anACurve->GetType() == GeomAbs_Ellipse)) {
478 newV = ElCLib::InPeriod(V, myvsup - 2. * M_PI, myvsup);
483 if (newV - mytolv > myvsup) {
485 } else if (newV > myvsup) {
492 if ( !IsExtremum (U, V, P, &(myS->ChangeSurface()), E, Dist2,
493 Standard_False, anExt.IsMin(i))) continue;
496 Dist2 = P.SquareDistance(E);
498 if (IsOriginalPnt(E, myPoint, myNbExt)) {
499 myPoint[myNbExt] = Extrema_POnSurf(U,V,E);
500 mySqDist[myNbExt] = Dist2;
508 //=======================================================================
511 //=======================================================================
513 Standard_Boolean Extrema_ExtPRevS::IsDone() const
519 //=======================================================================
522 //=======================================================================
524 Standard_Integer Extrema_ExtPRevS::NbExt() const
526 if (!IsDone()) { throw StdFail_NotDone(); }
531 //=======================================================================
534 //=======================================================================
536 Standard_Real Extrema_ExtPRevS::SquareDistance(const Standard_Integer N) const
538 if (!IsDone()) { throw StdFail_NotDone(); }
539 if ((N < 1) || (N > myNbExt)) { throw Standard_OutOfRange(); }
540 if (myIsAnalyticallyComputable)
541 return mySqDist[N-1];
543 return myExtPS.SquareDistance(N);
545 //=======================================================================
548 //=======================================================================
550 const Extrema_POnSurf& Extrema_ExtPRevS::Point(const Standard_Integer N) const
552 if (!IsDone()) { throw StdFail_NotDone(); }
553 if ((N < 1) || (N > myNbExt)) { throw Standard_OutOfRange(); }
554 if (myIsAnalyticallyComputable)
557 return myExtPS.Point(N);